diff --git a/.gitignore b/.gitignore index 7c93c36693..624f5220d2 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ *.sublime-project *.sublime-workspace /.vscode +/.idea # tests /panel/cypress diff --git a/.php_cs b/.php_cs index 5753edda5d..07cd80f9d3 100644 --- a/.php_cs +++ b/.php_cs @@ -44,9 +44,9 @@ return PhpCsFixer\Config::create() 'no_useless_return' => true, 'ordered_imports' => ['sort_algorithm' => 'alpha'], // 'phpdoc_add_missing_param_annotation' => ['only_untyped' => false], // adds params in the wrong order - // 'phpdoc_align' => ['align' => 'vertical'], // added in a second step + 'phpdoc_align' => ['align' => 'left'], 'phpdoc_indent' => true, - // 'phpdoc_scalar' => true, // added in a second step + 'phpdoc_scalar' => true, 'phpdoc_trim' => true, 'short_scalar_cast' => true, 'single_line_comment_style' => true, diff --git a/.travis.yml b/.travis.yml index a8dda417cd..2c9d78c702 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: php os: linux +dist: bionic sudo: false services: - memcached @@ -8,38 +9,46 @@ php: - 7.1 - 7.2 - 7.3 + - 7.4snapshot +jobs: + allow_failures: + - php: 7.4snapshot before_install: - - echo yes | pecl install -f apcu - - phpenv config-add ./tests/php.ini + # set up PHP config + - phpenv config-rm xdebug.ini || true # code coverage is generated with PCOV + - phpenv config-add tests/php.ini + + # ensure that the Composer config is valid + - composer validate install: - # Install composer packages, will also trigger dump-autoload - - composer self-update - - composer require phpunit/phpunit ^7 - - composer require friendsofphp/php-cs-fixer - - composer install --no-interaction --ignore-platform-reqs + # install Composer packages, will also trigger dump-autoload + - composer require -n --ignore-platform-reqs "phwoolcon/ci-pecl-cacher" "phpunit/phpunit:^7" "pcov/clobber" "friendsofphp/php-cs-fixer" "php-coveralls/php-coveralls" + - composer install -n --ignore-platform-reqs --no-suggest - # Install coveralls.phar - - wget -c -nc --retry-connrefused --tries=0 https://github.com/php-coveralls/php-coveralls/releases/download/v2.1.0/php-coveralls.phar - - chmod +x php-coveralls.phar - - php php-coveralls.phar --version + # install and cache PHP extensions + - ./vendor/bin/ci-pecl-install memcached + - ./vendor/bin/ci-pecl-install pcov before_script: - mkdir -p build/logs + - ./vendor/bin/pcov clobber - ls -al script: - - composer validate - ./vendor/bin/phpunit --coverage-clover build/logs/clover.xml - - PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --config .php_cs --verbose --diff --dry-run + - PHP_CS_FIXER_IGNORE_ENV=1 ./vendor/bin/php-cs-fixer fix --config .php_cs --verbose --diff --dry-run after_success: - - travis_retry php php-coveralls.phar -v + - travis_retry ./vendor/bin/php-coveralls -v cache: directories: + - vendor + - $HOME/.composer/cache - $HOME/.php-cs-fixer + - $HOME/pecl_cache matrix: fast_finish: true diff --git a/composer.json b/composer.json index 3b36fcc6c2..68df63e9ff 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "getkirby/cms", "description": "The Kirby 3 core", - "version": "3.2.5", + "version": "3.3.0", "license": "proprietary", "keywords": ["kirby", "cms", "core"], "homepage": "https://getkirby.com", @@ -40,7 +40,7 @@ } }, "scripts": { - "analyze": "phpstan analyse src", + "analyze": "phpstan analyse", "test": "phpunit --stderr --coverage-html=tests/coverage", "zip": "composer archive --format=zip --file=dist", "build": "./scripts/build", diff --git a/composer.lock b/composer.lock index bbc6a225b5..ed241cca01 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ed043f76d01c39662efae54a2c917b0a", + "content-hash": "b6f220540a714bd27218b0fea5f2aad6", "packages": [ { "name": "claviska/simpleimage", @@ -366,16 +366,16 @@ }, { "name": "psr/log", - "version": "1.1.0", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", "shasum": "" }, "require": { @@ -384,7 +384,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -409,20 +409,20 @@ "psr", "psr-3" ], - "time": "2018-11-20T15:27:04+00:00" + "time": "2019-11-01T11:05:21+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", "shasum": "" }, "require": { @@ -434,7 +434,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -468,7 +468,7 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "true/punycode", diff --git a/config/aliases.php b/config/aliases.php index 73ede86017..fc354a518e 100644 --- a/config/aliases.php +++ b/config/aliases.php @@ -32,6 +32,9 @@ 'database' => 'Kirby\Database\Database', 'db' => 'Kirby\Database\Db', + // exceptions + 'errorpageexception' => 'Kirby\Exception\ErrorPageException', + // http classes 'cookie' => 'Kirby\Http\Cookie', 'header' => 'Kirby\Http\Header', diff --git a/config/api/authentication.php b/config/api/authentication.php index 41ce7a1c1b..509a3462d3 100644 --- a/config/api/authentication.php +++ b/config/api/authentication.php @@ -7,7 +7,7 @@ // csrf token check if ($auth->type() === 'session' && $auth->csrf() === false) { - throw new PermissionException('Unauthenticated', 403); + throw new PermissionException('Unauthenticated'); } // get user from session or basic auth @@ -19,5 +19,5 @@ return $user; } - throw new PermissionException('Unauthenticated', 403); + throw new PermissionException('Unauthenticated'); }; diff --git a/config/api/collections.php b/config/api/collections.php index f0bcf7292d..bd817e9c6a 100644 --- a/config/api/collections.php +++ b/config/api/collections.php @@ -27,8 +27,7 @@ */ 'languages' => [ 'model' => 'language', - 'type' => 'Kirby\Cms\Languages', - 'view' => 'compact' + 'type' => 'Kirby\Cms\Languages' ], /** diff --git a/config/api/models/File.php b/config/api/models/File.php index 96978f4221..bf5e573f80 100644 --- a/config/api/models/File.php +++ b/config/api/models/File.php @@ -48,13 +48,16 @@ return $file->next(); }, 'nextWithTemplate' => function (File $file) { - $files = $file->templateSiblings()->sortBy('sort', 'asc'); + $files = $file->templateSiblings()->sortBy('sort', 'asc', 'filename', 'asc'); $index = $files->indexOf($file); return $files->nth($index + 1); }, + 'niceSize' => function (File $file) { + return $file->niceSize(); + }, 'options' => function (File $file) { - return $file->permissions()->toArray(); + return $file->panelOptions(); }, 'panelIcon' => function (File $file) { return $file->panelIcon(); @@ -69,32 +72,23 @@ return $file->prev(); }, 'prevWithTemplate' => function (File $file) { - $files = $file->templateSiblings()->sortBy('sort', 'asc'); + $files = $file->templateSiblings()->sortBy('sort', 'asc', 'filename', 'asc'); $index = $files->indexOf($file); return $files->nth($index - 1); }, - 'niceSize' => function (File $file) { - return $file->niceSize(); - }, - 'panelIcon' => function (File $file) { - return $file->panelIcon(); - }, - 'panelImage' => function (File $file) { - return $file->panelImage(); - }, 'parent' => function (File $file) { return $file->parent(); }, 'parents' => function (File $file) { return $file->parents()->flip(); }, - 'template' => function (File $file) { - return $file->template(); - }, 'size' => function (File $file) { return $file->size(); }, + 'template' => function (File $file) { + return $file->template(); + }, 'thumbs' => function ($file) { if ($file->isResizable() === false) { return null; diff --git a/config/api/models/Language.php b/config/api/models/Language.php index 77a633e336..9350a89350 100644 --- a/config/api/models/Language.php +++ b/config/api/models/Language.php @@ -31,12 +31,14 @@ ], 'type' => 'Kirby\Cms\Language', 'views' => [ - 'compact' => [ + 'default' => [ 'code', 'default', + 'direction', + 'locale', 'name', 'rules', - 'direction' + 'url' ] ] ]; diff --git a/config/api/models/Page.php b/config/api/models/Page.php index 91b145b916..1f8467b433 100644 --- a/config/api/models/Page.php +++ b/config/api/models/Page.php @@ -27,7 +27,7 @@ return $page->errors(); }, 'files' => function (Page $page) { - return $page->files()->sortBy('sort', 'asc'); + return $page->files()->sortBy('sort', 'asc', 'filename', 'asc'); }, 'hasChildren' => function (Page $page) { return $page->hasChildren(); @@ -56,7 +56,7 @@ return $page->num(); }, 'options' => function (Page $page) { - return $page->permissions()->toArray(); + return $page->panelOptions(['preview']); }, 'panelIcon' => function (Page $page) { return $page->panelIcon(); diff --git a/config/api/models/Site.php b/config/api/models/Site.php index 2913126f7e..ca5dfe0da0 100644 --- a/config/api/models/Site.php +++ b/config/api/models/Site.php @@ -24,7 +24,7 @@ return $site->drafts(); }, 'files' => function (Site $site) { - return $site->files()->sortBy('sort', 'asc'); + return $site->files()->sortBy('sort', 'asc', 'filename', 'asc'); }, 'options' => function (Site $site) { return $site->permissions()->toArray(); diff --git a/config/api/models/System.php b/config/api/models/System.php index 927ff2b21d..72fbd6e10e 100644 --- a/config/api/models/System.php +++ b/config/api/models/System.php @@ -98,7 +98,7 @@ 'isInstalled', 'isLocal', 'kirbytext', - 'languages' => 'compact', + 'languages', 'license', 'multilang', 'requirements', diff --git a/config/api/models/User.php b/config/api/models/User.php index 8fe2dc2ccb..f0c6b19397 100644 --- a/config/api/models/User.php +++ b/config/api/models/User.php @@ -24,7 +24,7 @@ return $user->email(); }, 'files' => function (User $user) { - return $user->files()->sortBy('sort', 'asc'); + return $user->files()->sortBy('sort', 'asc', 'filename', 'asc'); }, 'id' => function (User $user) { return $user->id(); @@ -39,7 +39,7 @@ return $user->next(); }, 'options' => function (User $user) { - return $user->permissions()->toArray(); + return $user->panelOptions(); }, 'permissions' => function (User $user) { return $user->role()->permissions()->toArray(); diff --git a/config/api/routes/files.php b/config/api/routes/files.php index c1c78f020a..8c5414e072 100644 --- a/config/api/routes/files.php +++ b/config/api/routes/files.php @@ -27,7 +27,7 @@ 'pattern' => '(:all)/files', 'method' => 'GET', 'action' => function (string $path) { - return $this->parent($path)->files()->sortBy('sort', 'asc'); + return $this->parent($path)->files()->sortBy('sort', 'asc', 'filename', 'asc'); } ], [ diff --git a/config/components.php b/config/components.php index 44949fa13b..776e7edc97 100644 --- a/config/components.php +++ b/config/components.php @@ -6,6 +6,7 @@ use Kirby\Cms\FileVersion; use Kirby\Cms\Template; use Kirby\Data\Data; +use Kirby\Http\Server; use Kirby\Image\Darkroom; use Kirby\Text\Markdown; use Kirby\Text\SmartyPants; @@ -26,6 +27,30 @@ return $url; }, + + /** + * Object and variable dumper + * to help with debugging. + * + * @param \Kirby\Cms\App $kirby Kirby instance + * @param mixed $variable + * @param bool $echo + * @return string + */ + 'dump' => function (App $kirby, $variable, bool $echo = true) { + if (Server::cli() === true) { + $output = print_r($variable, true) . PHP_EOL; + } else { + $output = '
' . print_r($variable, true) . ''; + } + + if ($echo === true) { + echo $output; + } + + return $output; + }, + /** * Modify URLs for file objects * diff --git a/config/fields/files.php b/config/fields/files.php index 2bf87c8612..9ecb0c157e 100644 --- a/config/fields/files.php +++ b/config/fields/files.php @@ -99,10 +99,13 @@ $field = $this->field(); return $field->filepicker([ - 'query' => $field->query(), - 'image' => $field->image(), - 'info' => $field->info(), - 'text' => $field->text() + 'image' => $field->image(), + 'info' => $field->info(), + 'limit' => $field->limit(), + 'page' => $this->requestQuery('page'), + 'query' => $field->query(), + 'search' => $this->requestQuery('search'), + 'text' => $field->text() ]); } ], diff --git a/config/fields/info.php b/config/fields/info.php index 15c0a27903..7e36a9d217 100644 --- a/config/fields/info.php +++ b/config/fields/info.php @@ -15,7 +15,8 @@ 'text' => function () { if ($text = $this->text) { $text = $this->model()->toString($text); - return kirbytext($text); + $text = $this->kirby()->kirbytext($text); + return $text; } } ], diff --git a/config/fields/mixins/filepicker.php b/config/fields/mixins/filepicker.php index d288f8897b..ba812300c6 100644 --- a/config/fields/mixins/filepicker.php +++ b/config/fields/mixins/filepicker.php @@ -1,40 +1,14 @@ [ 'filepicker' => function (array $params = []) { - // fetch the parent model - $model = $this->model(); - - // find the right default query - if (empty($params['query']) === false) { - $query = $params['query']; - } elseif (is_a($model, 'Kirby\Cms\File') === true) { - $query = 'file.siblings'; - } else { - $query = $model::CLASS_ALIAS . '.files'; - } - - // fetch all files for the picker - $files = $model->query($query, 'Kirby\Cms\Files'); - $data = []; - - // prepare the response for each file - foreach ($files as $index => $file) { - if (empty($params['map']) === false) { - $data[] = $params['map']($file); - } else { - $data[] = $file->panelPickerData([ - 'image' => $params['image'] ?? [], - 'info' => $params['info'] ?? false, - 'model' => $model, - 'text' => $params['text'] ?? '{{ file.filename }}', - ]); - } - } + $params['model'] = $this->model(); - return $data; + return (new FilePicker($params))->toArray(); } ] ]; diff --git a/config/fields/mixins/pagepicker.php b/config/fields/mixins/pagepicker.php index d0a8186a7a..bbdc86e594 100644 --- a/config/fields/mixins/pagepicker.php +++ b/config/fields/mixins/pagepicker.php @@ -1,49 +1,14 @@ [ 'pagepicker' => function (array $params = []) { - $query = $params['query'] ?? null; - $model = $this->model(); - $site = $this->kirby()->site(); - - if ($query) { - $pages = $model->query($query, 'Kirby\Cms\Pages'); - $self = null; - } else { - if (!$parent = $site->find($params['parent'] ?? null)) { - $parent = $site; - } - - $pages = $parent->children(); - $self = [ - 'id' => $parent->id() == '' ? null : $parent->id(), - 'title' => $parent->title()->value(), - 'parent' => is_a($parent->parent(), 'Kirby\Cms\Page') === true ? $parent->parent()->id() : null, - ]; - } - - $children = []; - - foreach ($pages as $index => $page) { - if ($page->isReadable() === true) { - if (empty($params['map']) === false) { - $children[] = $params['map']($page); - } else { - $children[] = $page->panelPickerData([ - 'image' => $params['image'] ?? [], - 'info' => $params['info'] ?? false, - 'model' => $model, - 'text' => $params['text'] ?? null, - ]); - } - } - } + // inject the current model + $params['model'] = $this->model(); - return [ - 'model' => $self, - 'pages' => $children - ]; + return (new PagePicker($params))->toArray(); } ] ]; diff --git a/config/fields/mixins/picker.php b/config/fields/mixins/picker.php index 028eb66089..a04ac9584f 100644 --- a/config/fields/mixins/picker.php +++ b/config/fields/mixins/picker.php @@ -53,6 +53,13 @@ return $query; }, + /** + * Enable/disable the search field in the picker + */ + 'search' => function (bool $search = true) { + return $search; + }, + /** * Main text for each item */ diff --git a/config/fields/mixins/userpicker.php b/config/fields/mixins/userpicker.php index 1432bed35d..41c2b62e01 100644 --- a/config/fields/mixins/userpicker.php +++ b/config/fields/mixins/userpicker.php @@ -1,44 +1,13 @@ [ 'userpicker' => function (array $params = []) { + $params['model'] = $this->model(); - // fetch the parent model - $model = $this->model(); - - // find the right default query - if (empty($params['query']) === false) { - $query = $params['query']; - } elseif (is_a($model, 'Kirby\Cms\User') === true) { - $query = 'user.siblings'; - } else { - $query = 'kirby.users'; - } - - // fetch all users for the picker - $users = $model->query($query, 'Kirby\Cms\Users'); - $data = []; - - if (!$users) { - return []; - } - - // prepare the response for each user - foreach ($users->sortBy('username', 'asc') as $index => $user) { - if (empty($params['map']) === false) { - $data[] = $params['map']($user); - } else { - $data[] = $user->panelPickerData([ - 'image' => $params['image'] ?? [], - 'info' => $params['info'] ?? false, - 'model' => $model, - 'text' => $params['text'] ?? '{{ user.username }}', - ]); - } - } - - return $data; + return (new UserPicker($params))->toArray(); } ] ]; diff --git a/config/fields/pages.php b/config/fields/pages.php index 1c8a6c9939..9b4a3c21c6 100644 --- a/config/fields/pages.php +++ b/config/fields/pages.php @@ -43,6 +43,13 @@ return $size; }, + /** + * Optionally include subpages of pages + */ + 'subpages' => function (bool $subpages = true) { + return $subpages; + }, + 'value' => function ($value = null) { return $this->toPages($value); }, @@ -86,11 +93,15 @@ $field = $this->field(); return $field->pagepicker([ - 'image' => $field->image(), - 'info' => $field->info(), - 'parent' => $this->requestQuery('parent'), - 'query' => $field->query(), - 'text' => $field->text() + 'image' => $field->image(), + 'info' => $field->info(), + 'limit' => $field->limit(), + 'page' => $this->requestQuery('page'), + 'parent' => $this->requestQuery('parent'), + 'query' => $field->query(), + 'search' => $this->requestQuery('search'), + 'subpages' => $field->subpages(), + 'text' => $field->text() ]); } ] diff --git a/config/fields/structure.php b/config/fields/structure.php index d92507745c..1eb27ba799 100644 --- a/config/fields/structure.php +++ b/config/fields/structure.php @@ -84,6 +84,10 @@ return $this->rows($this->value); }, 'fields' => function () { + if (empty($this->fields) === true) { + throw new Exception('Please provide some fields for the structure'); + } + return $this->form()->fields()->toArray(); }, 'columns' => function () { diff --git a/config/fields/users.php b/config/fields/users.php index 6b7fe6515d..bc96bd46fe 100644 --- a/config/fields/users.php +++ b/config/fields/users.php @@ -75,17 +75,20 @@ $field = $this->field(); return $field->userpicker([ - 'query' => $field->query(), - 'image' => $field->image(), - 'info' => $field->info(), - 'text' => $field->text() + 'image' => $field->image(), + 'info' => $field->info(), + 'limit' => $field->limit(), + 'page' => $this->requestQuery('page'), + 'query' => $field->query(), + 'search' => $this->requestQuery('search'), + 'text' => $field->text() ]); } ] ]; }, 'save' => function ($value = null) { - return A::pluck($value, 'email'); + return A::pluck($value, 'id'); }, 'validations' => [ 'max', diff --git a/config/helpers.php b/config/helpers.php index f88d5ef422..7d570bff22 100755 --- a/config/helpers.php +++ b/config/helpers.php @@ -5,7 +5,6 @@ use Kirby\Cms\Html; use Kirby\Cms\Response; use Kirby\Cms\Url; -use Kirby\Http\Server; use Kirby\Toolkit\Escape; use Kirby\Toolkit\F; use Kirby\Toolkit\I18n; @@ -55,7 +54,7 @@ function collection(string $name) * Checks / returns a CSRF token * * @param string $check Pass a token here to compare it to the one in the session - * @return string|boolean Either the token or a boolean check result + * @return string|bool Either the token or a boolean check result */ function csrf(string $check = null) { @@ -89,7 +88,7 @@ function csrf(string $check = null) * @param string|array $options Pass an array of attributes for the link tag or a media attribute string * @return string|null */ -function css($url, $options = null) +function css($url, $options = null): ?string { if (is_array($url) === true) { $links = array_map(function ($url) use ($options) { @@ -121,27 +120,33 @@ function css($url, $options = null) return ''; } +/** + * Triggers a deprecation warning if debug mode is active + * + * @param string $message + * @return bool Whether the warning was triggered + */ +function deprecated(string $message): bool +{ + if (App::instance()->option('debug') === true) { + return trigger_error($message, E_USER_DEPRECATED) === true; + } + + return false; +} + /** * Simple object and variable dumper * to help with debugging. * * @param mixed $variable - * @param boolean $echo + * @param bool $echo * @return string */ function dump($variable, bool $echo = true): string { - if (Server::cli() === true) { - $output = print_r($variable, true) . PHP_EOL; - } else { - $output = '
' . print_r($variable, true) . ''; - } - - if ($echo === true) { - echo $output; - } - - return $output; + $kirby = App::instance(); + return $kirby->component('dump')($kirby, $variable, $echo); } /** @@ -159,10 +164,10 @@ function e($condition, $value, $alternative = null) /** * Escape context specific output * - * @param string $string Untrusted data - * @param string $context Location of output - * @param boolean $strict Whether to escape an extended set of characters (HTML attributes only) - * @return string Escaped data + * @param string $string Untrusted data + * @param string $context Location of output + * @param bool $strict Whether to escape an extended set of characters (HTML attributes only) + * @return string Escaped data */ function esc($string, $context = 'html', $strict = false) { @@ -177,9 +182,9 @@ function esc($string, $context = 'html', $strict = false) /** * Shortcut for $kirby->request()->get() * - * @param mixed $key The key to look for. Pass false or null to return the entire request array. - * @param mixed $default Optional default value, which should be returned if no element has been found - * @return mixed + * @param mixed $key The key to look for. Pass false or null to return the entire request array. + * @param mixed $default Optional default value, which should be returned if no element has been found + * @return mixed */ function get($key = null, $default = null) { @@ -206,7 +211,7 @@ function gist(string $url, string $file = null): string * Urls can be relative or absolute. * * @param string $url - * @param integer $code + * @param int $code * @return void */ function go(string $url = null, int $code = 302) @@ -348,9 +353,9 @@ function invalid(array $data = [], array $rules = [], array $messages = []) * * @param string|array $url * @param string|array $options - * @return void + * @return string|null */ -function js($url, $options = null) +function js($url, $options = null): ?string { if (is_array($url) === true) { $scripts = array_map(function ($url) use ($options) { @@ -589,7 +594,7 @@ function r($condition, $value, $alternative = null) * by the defined step * * @param string $date - * @param integer $step + * @param int $step * @return string|null */ function timestamp(string $date = null, int $step = null): ?string @@ -671,7 +676,7 @@ function smartypants(string $text = null): string * * @param string|array $name * @param array|object $data - * @param boolean $return + * @param bool $return * @return string */ function snippet($name, $data = [], bool $return = false) @@ -693,11 +698,20 @@ function snippet($name, $data = [], bool $return = false) * Includes an SVG file by absolute or * relative file path. * - * @param string $file - * @return string + * @param string|\Kirby\Cms\File $file + * @return string|false */ -function svg(string $file) +function svg($file) { + // support for Kirby's file objects + if (is_a($file, 'Kirby\Cms\File') === true && $file->extension() === 'svg') { + return $file->read(); + } + + if (is_string($file) === false) { + return false; + } + $extension = F::extension($file); // check for valid svg files @@ -721,9 +735,9 @@ function svg(string $file) /** * Returns translate string for key from translation file * - * @param string|array $key - * @param string|null $fallback - * @return mixed + * @param string|array $key + * @param string|null $fallback + * @return mixed */ function t($key, string $fallback = null) { @@ -733,9 +747,9 @@ function t($key, string $fallback = null) /** * Translates a count * - * @param string|array $key - * @param int $count - * @return mixed + * @param string|array $key + * @param int $count + * @return mixed */ function tc($key, int $count) { @@ -825,7 +839,7 @@ function video(string $url, array $options = [], array $attr = []): string */ function vimeo(string $url, array $options = [], array $attr = []): string { - return Html::video($url, $options, $attr); + return Html::vimeo($url, $options, $attr); } /** @@ -851,5 +865,5 @@ function widont(string $string = null): string */ function youtube(string $url, array $options = [], array $attr = []): string { - return Html::video($url, $options, $attr); + return Html::youtube($url, $options, $attr); } diff --git a/config/methods.php b/config/methods.php index 51ba2da5b5..36cda009ba 100644 --- a/config/methods.php +++ b/config/methods.php @@ -28,7 +28,7 @@ * Converts the field value into a proper boolean and inverts it * * @param \Kirby\Cms\Field $field - * @return boolean + * @return bool */ 'isFalse' => function (Field $field): bool { return $field->toBool() === false; @@ -38,7 +38,7 @@ * Converts the field value into a proper boolean * * @param \Kirby\Cms\Field $field - * @return boolean + * @return bool */ 'isTrue' => function (Field $field): bool { return $field->toBool() === true; @@ -49,7 +49,7 @@ * * @param string $validator * @param mixed ...$arguments A list of optional validator arguments - * @return boolean + * @return bool */ 'isValid' => function (Field $field, string $validator, ...$arguments): bool { return V::$validator($field->value, ...$arguments); @@ -193,7 +193,7 @@ * @param \Kirby\Cms\Field $field * @return \Kirby\Cms\Page|null */ - 'toPage' => function (Field $field) use ($app) { + 'toPage' => function (Field $field) { return $field->toPages()->first(); }, @@ -254,7 +254,7 @@ * @param \Kirby\Cms\Field $field * @return \Kirby\Cms\User|null */ - 'toUser' => function (Field $field) use ($app) { + 'toUser' => function (Field $field) { return $field->toUsers()->first(); }, @@ -305,7 +305,7 @@ * * @param \Kirby\Cms\Field $field * @param int $cahrs - * @param boolean $strip + * @param bool $strip * @param string $rep * @return \Kirby\Cms\Field */ @@ -325,6 +325,17 @@ return $field; }, + /** + * Converts all line breaks in the field content to `
');
+ return $field;
+ },
+
/**
* Converts the field content to lowercase
*
diff --git a/config/roots.php b/config/roots.php
index b9621deae8..c473763060 100644
--- a/config/roots.php
+++ b/config/roots.php
@@ -11,18 +11,11 @@
return $roots['kirby'] . '/i18n';
},
'i18n:translations' => function (array $roots) {
- return $roots['translations'];
+ return $roots['i18n'] . '/translations';
},
'i18n:rules' => function (array $roots) {
return $roots['i18n'] . '/rules';
},
- /**
- * @deprecated 3.2.0 Use `i18n:translations` instead
- * @TODO move logic over to i18n:translations before removing
- */
- 'translations' => function (array $roots) {
- return $roots['i18n'] . '/translations';
- },
// index
'index' => function (array $roots) {
diff --git a/config/routes.php b/config/routes.php
index b12cf61a60..abd07a09ea 100644
--- a/config/routes.php
+++ b/config/routes.php
@@ -1,12 +1,12 @@
$media . '/plugins/(:any)/(:any)/(:all).(css|gif|js|jpg|png|svg|webp|woff2|woff)',
'env' => 'media',
- 'action' => function (string $provider, string $pluginName, string $filename, string $extension) use ($kirby) {
+ 'action' => function (string $provider, string $pluginName, string $filename, string $extension) {
return PluginAssets::resolve($provider . '/' . $pluginName, $filename . '.' . $extension);
}
],
@@ -102,7 +102,7 @@
[
'pattern' => $media . '/assets/(:all)/(:any)/(:any)',
'env' => 'media',
- 'action' => function ($path, $hash, $filename) use ($kirby) {
+ 'action' => function ($path, $hash, $filename) {
return Media::thumb($path, $hash, $filename);
}
]
@@ -110,73 +110,7 @@
// Multi-language setup
if ($kirby->multilang() === true) {
-
- // Multi-language home
- $after[] = [
- 'pattern' => '',
- 'method' => 'ALL',
- 'env' => 'site',
- 'action' => function () use ($kirby) {
- $home = $kirby->site()->homePage();
-
- // language detection on the home page with / as URL
- if ($home && $kirby->url() !== $home->url()) {
- if ($kirby->option('languages.detect') === true) {
- return $kirby
- ->response()
- ->redirect($kirby->detectedLanguage()->url());
- } else {
- return $kirby
- ->response()
- ->redirect($kirby->site()->url());
- }
-
- // default home page
- } else {
- return $kirby->defaultLanguage()->router()->call();
- }
- }
- ];
-
- foreach ($kirby->languages() as $language) {
- $after[] = [
- 'pattern' => trim($language->pattern() . '/(:all?)', '/'),
- 'method' => 'ALL',
- 'env' => 'site',
- 'action' => function ($path = null) use ($kirby, $language) {
- return $language->router()->call($path);
- }
- ];
- }
-
- // fallback route for unprefixed default language URLs.
- $after[] = [
- 'pattern' => '(:all)',
- 'method' => 'ALL',
- 'env' => 'site',
- 'action' => function (string $path) use ($kirby) {
-
- // check for content representations or files
- $extension = F::extension($path);
-
- // try to redirect prefixed pages
- if (empty($extension) === true && $page = $kirby->page($path)) {
- $url = $kirby->request()->url([
- 'query' => null,
- 'params' => null,
- 'fragment' => null
- ]);
-
- if ($url->toString() !== $page->url()) {
- return $kirby
- ->response()
- ->redirect($page->url());
- }
- }
-
- return $kirby->defaultLanguage()->router()->call($path);
- }
- ];
+ $after = LanguageRoutes::create($kirby);
} else {
// Single-language home
diff --git a/config/sections/files.php b/config/sections/files.php
index 7df73fa105..2f7e6f23fd 100644
--- a/config/sections/files.php
+++ b/config/sections/files.php
@@ -15,6 +15,12 @@
'parent',
],
'props' => [
+ /**
+ * Enables/disables reverse sorting
+ */
+ 'flip' => function (bool $flip = false) {
+ return $flip;
+ },
/**
* Image options to control the source and look of file previews
*/
@@ -83,6 +89,11 @@
$files = $files->sortBy('sort', 'asc', 'filename', 'asc');
}
+ // flip
+ if ($this->flip === true) {
+ $files = $files->flip();
+ }
+
// apply the default pagination
$files = $files->paginate([
'page' => $this->page,
@@ -168,6 +179,10 @@
return false;
}
+ if ($this->flip === true) {
+ return false;
+ }
+
return true;
},
'upload' => function () {
diff --git a/config/sections/info.php b/config/sections/info.php
index 8c9fd4c746..254a76ba01 100644
--- a/config/sections/info.php
+++ b/config/sections/info.php
@@ -19,7 +19,6 @@
if ($this->text) {
$text = $this->model()->toString($this->text);
$text = $this->kirby()->kirbytext($text);
-
return $text;
}
},
diff --git a/config/sections/mixins/help.php b/config/sections/mixins/help.php
index f0301ea9ba..80f42ee613 100644
--- a/config/sections/mixins/help.php
+++ b/config/sections/mixins/help.php
@@ -14,7 +14,9 @@
'computed' => [
'help' => function () {
if ($this->help) {
- return $this->model()->toString($this->help);
+ $help = $this->model()->toString($this->help);
+ $help = $this->kirby()->kirbytext($help);
+ return $help;
}
}
]
diff --git a/config/sections/mixins/pagination.php b/config/sections/mixins/pagination.php
index 367781b828..8bf3deebda 100644
--- a/config/sections/mixins/pagination.php
+++ b/config/sections/mixins/pagination.php
@@ -14,7 +14,7 @@
* Sets the default page for the pagination. This will overwrite default pagination.
*/
'page' => function (int $page = null) {
- return get('page', $page ?? 1);
+ return get('page', $page);
},
],
'methods' => [
diff --git a/config/sections/pages.php b/config/sections/pages.php
index fac4c71d95..9fd99e3659 100644
--- a/config/sections/pages.php
+++ b/config/sections/pages.php
@@ -20,7 +20,13 @@
* Optional array of templates that should only be allowed to add.
*/
'create' => function ($add = null) {
- return A::wrap($add);
+ return $add;
+ },
+ /**
+ * Enables/disables reverse sorting
+ */
+ 'flip' => function (bool $flip = false) {
+ return $flip;
},
/**
* Image options to control the source and look of page previews
@@ -122,6 +128,11 @@
$pages = $pages->sortBy(...$pages::sortArgs($this->sortBy));
}
+ // flip
+ if ($this->flip === true) {
+ $pages = $pages->flip();
+ }
+
// pagination
$pages = $pages->paginate([
'page' => $this->page,
@@ -188,6 +199,10 @@
];
},
'add' => function () {
+ if ($this->create === false) {
+ return false;
+ }
+
if (in_array($this->status, ['draft', 'all']) === false) {
return false;
}
@@ -222,13 +237,17 @@
return false;
}
+ if ($this->flip === true) {
+ return false;
+ }
+
return true;
}
],
'methods' => [
'blueprints' => function () {
$blueprints = [];
- $templates = empty($this->create) === false ? $this->create : $this->templates;
+ $templates = empty($this->create) === false ? A::wrap($this->create) : $this->templates;
if (empty($templates) === true) {
$templates = $this->kirby()->blueprints();
diff --git a/config/tags.php b/config/tags.php
index 955478e535..63eb9a4439 100644
--- a/config/tags.php
+++ b/config/tags.php
@@ -98,7 +98,6 @@
'linkclass',
'rel',
'target',
- 'text',
'title',
'width'
],
diff --git a/i18n/translations/bg.json b/i18n/translations/bg.json
index 920484f37c..cc81f55020 100644
--- a/i18n/translations/bg.json
+++ b/i18n/translations/bg.json
@@ -23,6 +23,7 @@
"delete": "\u0418\u0437\u0442\u0440\u0438\u0439",
"dimensions": "Размери",
+ "disabled": "Disabled",
"discard": "\u041e\u0442\u043c\u0435\u043d\u0438",
"download": "Download",
"duplicate": "Duplicate",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Секция \"{name}\" не може да бъде заредена",
"error.section.type.invalid": "Типът \"{type}\" на секция не е валиден",
+ "error.site.changeTitle.empty": "Заглавието е задължително",
"error.site.changeTitle.permission":
"Не може да променяте заглавието на сайта",
"error.site.update.permission": "Нямате права за да обновите сайта",
@@ -155,6 +157,8 @@
"Ролята на последния администратор не може да бъде променена",
"error.user.changeRole.permission":
"Нямате права да промените ролята на този потребител \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "Нямате права да създадете този потребител",
"error.user.delete": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f\u0442 \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0438\u0437\u0442\u0440\u0438\u0442",
"error.user.delete.lastAdmin": "\u041d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u0430 \u0438\u0437\u0442\u0440\u0438\u0435\u0442\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440",
@@ -219,6 +223,7 @@
"error.validation.time": "Моля въведете валидно време",
"error.validation.url": "Моля въведете валиден URL",
+ "field.required": "The field is required",
"field.files.empty": "Все още не са избрани файлове",
"field.pages.empty": "Все още не са избрани страници",
"field.structure.delete.confirm": "Сигурни ли сте, че искате да изтриете това вписване?",
@@ -291,6 +296,7 @@
"loading": "Зареждане",
"lock.unsaved": "Unsaved changes",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Unsaved changes by {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Published",
"pages.status.unlisted": "Скрит",
+ "pagination.page": "Страница",
+
"password": "\u041f\u0430\u0440\u043e\u043b\u0430",
"pixel": "Пиксел",
"prev": "Previous",
@@ -384,6 +392,9 @@
"save": "\u0417\u0430\u043f\u0438\u0448\u0438",
"search": "Търси",
+
+ "section.required": "The section is required",
+
"select": "Избери",
"settings": "Настройки",
"size": "Размер",
diff --git a/i18n/translations/ca.json b/i18n/translations/ca.json
index b787e1c3d3..c2b3006f43 100644
--- a/i18n/translations/ca.json
+++ b/i18n/translations/ca.json
@@ -23,6 +23,7 @@
"delete": "Eliminar",
"dimensions": "Dimensions",
+ "disabled": "Desactivat",
"discard": "Descartar",
"download": "Descarregar",
"duplicate": "Duplicar",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "No s'ha pogut carregar la secció \"{name}\"",
"error.section.type.invalid": "La secció tipus \"{type}\" no és vàlida",
+ "error.site.changeTitle.empty": "El títol no pot estar buit",
"error.site.changeTitle.permission":
"No tens permís per canviar el títol del lloc web",
"error.site.update.permission": "No tens permís per actualitzar el lloc web",
@@ -155,6 +157,8 @@
"El rol del darrer administrador no es pot canviar",
"error.user.changeRole.permission":
"No tens permís per canviar el rol de l'usuari \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "No tens permís per promocionar algú al rol d’administrador",
"error.user.create.permission": "No tens permís per crear aquest usuari",
"error.user.delete": "L'usuari \"{name}\" no es pot eliminar",
"error.user.delete.lastAdmin": "No es pot eliminar l'\u00faltim administrador",
@@ -219,6 +223,7 @@
"error.validation.time": "Si us plau, introduïu una hora vàlida",
"error.validation.url": "Si us plau, introduïu una URL vàlida",
+ "field.required": "El camp és obligatori",
"field.files.empty": "Encara no hi ha cap fitxer seleccionat",
"field.pages.empty": "Encara no s'ha seleccionat cap pàgina",
"field.structure.delete.confirm": "Segur que voleu eliminar aquesta fila?",
@@ -291,6 +296,7 @@
"loading": "Carregant",
"lock.unsaved": "Canvis no guardats",
+ "lock.unsaved.empty": "Ja no hi ha canvis no guardats",
"lock.isLocked": "Canvis no guardats per {email}",
"lock.file.isLocked": "El fitxer està sent editat actualment per {email} i no pot ser modificat.",
"lock.page.isLocked": "La pàgina està sent editat actualment per {email} i no pot ser modificat.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Publicat",
"pages.status.unlisted": "Sense classificar",
+ "pagination.page": "Pàgina",
+
"password": "Contrasenya",
"pixel": "Pixel",
"prev": "Anterior",
@@ -384,6 +392,9 @@
"save": "Desar",
"search": "Cercar",
+
+ "section.required": "La secció és obligatòria",
+
"select": "Seleccionar",
"settings": "Configuració",
"size": "Tamany",
@@ -418,7 +429,7 @@
"upload.error.default": "No s'ha pogut carregar el fitxer",
"upload.error.extension": "La càrrega del fitxer s'ha aturat per l'extensió",
"upload.error.formSize": "El fitxer carregat supera la directiva MAX_FILE_SIZE especificada en el formulari",
- "upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
+ "upload.error.iniPostSize": "El fitxer carregat supera la directiva post_max_size especifiada al php.ini",
"upload.error.iniSize": "El fitxer carregat supera la directiva upload_max_filesize especifiada al php.ini",
"upload.error.noFile": "No s'ha carregat cap fitxer",
"upload.error.noFiles": "No s'ha penjat cap fitxer",
diff --git a/i18n/translations/cs.json b/i18n/translations/cs.json
index f5535a6a7b..0091380c71 100644
--- a/i18n/translations/cs.json
+++ b/i18n/translations/cs.json
@@ -23,6 +23,7 @@
"delete": "Smazat",
"dimensions": "Rozměry",
+ "disabled": "Zakázáno",
"discard": "Zahodit",
"download": "Stáhnout",
"duplicate": "Duplikovat",
@@ -37,7 +38,7 @@
"error.access.login": "Neplatné přihlášení",
"error.access.panel": "Nemáte povoleno vstoupit do panelu",
- "error.access.view": "You are not allowed to access this part of the panel",
+ "error.access.view": "Nejste oprávněni vstoupit do této části panelu.",
"error.avatar.create.fail": "Nebylo možné nahrát profilový obrázek",
"error.avatar.delete.fail": "Nebylo mo\u017en\u00e9 smazat profilov\u00fd obr\u00e1zek",
@@ -52,7 +53,7 @@
"error.field.converter.invalid": "Neplatný konvertor \"{converter}\"",
- "error.file.changeName.empty": "The name must not be empty",
+ "error.file.changeName.empty": "Toto jméno nesmí být prázdné",
"error.file.changeName.permission":
"Nemáte povoleno změnit jméno souboru \"{filename}\"",
"error.file.duplicate": "Soubor s názvem \"{filename}\" již existuje",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Nelze načíst sekci \"{name}\"",
"error.section.type.invalid": "Typ sekce \"{type}\" není platný",
+ "error.site.changeTitle.empty": "Titulek nesmí být prázdný",
"error.site.changeTitle.permission":
"Nemáte dovoleno změnit titulek stránky",
"error.site.update.permission": "Nemáte dovoleno upravit stránku",
@@ -155,6 +157,8 @@
"Role posledního administrátora nemůže být změněna",
"error.user.changeRole.permission":
"Nemáte dovoleno změnit roli uživatele \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "Nemáte dovoleno povýšit uživatele do role administrátora.",
"error.user.create.permission": "Nemáte dovoleno vytvořit tohoto uživatele",
"error.user.delete": "U\u017eivatel nemohl b\u00fdt smaz\u00e1n",
"error.user.delete.lastAdmin": "Nem\u016f\u017eete smazat posledn\u00edho administr\u00e1tora",
@@ -219,6 +223,7 @@
"error.validation.time": "Zadejte prosím platný čas",
"error.validation.url": "Zadejte prosím platnou adresu URL",
+ "field.required": "The field is required",
"field.files.empty": "Nebyly zatím vybrány žádné soubory",
"field.pages.empty": "Nebyly zatím vybrány žádné stránky",
"field.structure.delete.confirm": "Opravdu chcete smazat tento z\u00e1znam?",
@@ -291,6 +296,7 @@
"loading": "Načítám",
"lock.unsaved": "Neuložené změny",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Neuložené změny provedené {email}",
"lock.file.isLocked": "Soubor nelze změnit, právě jej upravuje {email}.",
"lock.page.isLocked": "Stránku nelze změnit, právě jí upravuje {email} .",
@@ -364,6 +370,8 @@
"pages.status.listed": "Zveřejněno",
"pages.status.unlisted": "Neveřejná",
+ "pagination.page": "Stránka",
+
"password": "Heslo",
"pixel": "Pixel",
"prev": "Předchozí",
@@ -384,6 +392,9 @@
"save": "Ulo\u017eit",
"search": "Hledat",
+
+ "section.required": "The section is required",
+
"select": "Vybrat",
"settings": "Nastavení",
"size": "Velikost",
@@ -413,9 +424,9 @@
"translation.name": "\u010cesky",
"upload": "Nahrát",
- "upload.error.cantMove": "The uploaded file could not be moved",
- "upload.error.cantWrite": "Failed to write file to disk",
- "upload.error.default": "The file could not be uploaded",
+ "upload.error.cantMove": "Nahraný soubor nemohl být přesunut",
+ "upload.error.cantWrite": "Zápis souboru na disk se nezdařil",
+ "upload.error.default": "Soubor se nepodařilo nahrát",
"upload.error.extension": "File upload stopped by extension",
"upload.error.formSize": "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the form",
"upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
diff --git a/i18n/translations/da.json b/i18n/translations/da.json
index 7b4a533847..5ead973b98 100644
--- a/i18n/translations/da.json
+++ b/i18n/translations/da.json
@@ -23,6 +23,7 @@
"delete": "Slet",
"dimensions": "Dimensioner",
+ "disabled": "Disabled",
"discard": "Kass\u00e9r",
"download": "Download",
"duplicate": "Dupliker",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Sektionen \"{section}\" kunne ikke indlæses",
"error.section.type.invalid": "Sektionstypen \"{type}\" er ikke gyldig",
+ "error.site.changeTitle.empty": "Titlen kan ikke være tom",
"error.site.changeTitle.permission":
"Du har ikke tilladelse til at ændre titlen på sitet",
"error.site.update.permission": "Du har ikke tilladelse til at opdatere sitet",
@@ -155,6 +157,8 @@
"Rollen for den sidste admin kan ikke ændres",
"error.user.changeRole.permission":
"Du har ikke tilladelse til at ændre rollen for brugeren \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "Du har ikke tilladelse til at oprette denne bruger",
"error.user.delete": "Brugeren kunne ikke slettes",
"error.user.delete.lastAdmin": "Du kan ikke slette den sidste admin",
@@ -219,6 +223,7 @@
"error.validation.time": "Indtast venligst et gyldigt tidspunkt",
"error.validation.url": "Indtast venligst en gyldig URL",
+ "field.required": "The field is required",
"field.files.empty": "Ingen filer valgt endnu",
"field.pages.empty": "Ingen sider valgt endnu",
"field.structure.delete.confirm": "\u00d8nsker du virkelig at slette denne indtastning?",
@@ -291,6 +296,7 @@
"loading": "Indlæser",
"lock.unsaved": "Ugemte ændringer",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Ugemte ændringer af {email}",
"lock.file.isLocked": "Filen redigeres på nuværende af {email} og kan derfor ikke ændres.",
"lock.page.isLocked": "Siden redigeres på nuværende af {email} og kan derfor ikke ændres.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Udgivede",
"pages.status.unlisted": "Ulistede",
+ "pagination.page": "Side",
+
"password": "Adgangskode",
"pixel": "Pixel",
"prev": "Forrige",
@@ -384,6 +392,9 @@
"save": "Gem",
"search": "Søg",
+
+ "section.required": "The section is required",
+
"select": "Vælg",
"settings": "Indstillinger",
"size": "Størrelse",
@@ -418,7 +429,7 @@
"upload.error.default": "Filen kunne ikke uploades",
"upload.error.extension": "Upload af filen blev stoppet af dens type",
"upload.error.formSize": "Filen overskrider MAX_FILE_SIZE direktivet der er specificeret for formularen",
- "upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
+ "upload.error.iniPostSize": "FIlen overskrider post_max_size direktivet i php.ini",
"upload.error.iniSize": "FIlen overskrider upload_max_filesize direktivet i php.ini",
"upload.error.noFile": "Ingen fil blev uploadet",
"upload.error.noFiles": "Ingen filer blev uploadet",
diff --git a/i18n/translations/de.json b/i18n/translations/de.json
index cb03073461..2f55a61538 100644
--- a/i18n/translations/de.json
+++ b/i18n/translations/de.json
@@ -23,6 +23,7 @@
"delete": "L\u00f6schen",
"dimensions": "Maße",
+ "disabled": "Gesperrt",
"discard": "Verwerfen",
"download": "Download",
"duplicate": "Duplizieren",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Der Bereich \"{name}\" konnte nicht geladen werden",
"error.section.type.invalid": "Der Bereichstyp \"{type}\" ist nicht gültig",
+ "error.site.changeTitle.empty": "Bitte gib einen Titel an",
"error.site.changeTitle.permission":
"Du kannst den Titel der Seite nicht ändern",
"error.site.update.permission": "Du darfst die Seite nicht editieren",
@@ -155,6 +157,8 @@
"Die Rolle des letzten Administrators kann nicht geändert werden",
"error.user.changeRole.permission":
"Du kannst die Rolle für den Benutzer \"{name}\" nicht ändern",
+ "error.user.changeRole.toAdmin":
+ "Du darfst die Admin Rolle nicht an andere Benutzer vergeben",
"error.user.create.permission": "Du kannst diesen Benutzer nicht anlegen",
"error.user.delete": "Der Benutzer \"{name}\" konnte nicht gelöscht werden",
"error.user.delete.lastAdmin": "Du kannst den letzten Admin nicht l\u00f6schen",
@@ -219,6 +223,7 @@
"error.validation.time": "Bitte gib eine gültige Uhrzeit ein",
"error.validation.url": "Bitte gib eine gültige URL ein",
+ "field.required": "Das Feld ist Pflicht",
"field.files.empty": "Keine Dateien ausgewählt",
"field.pages.empty": "Keine Seiten ausgewählt",
"field.structure.delete.confirm": "Willst du diesen Eintrag wirklich l\u00f6schen?",
@@ -291,6 +296,7 @@
"loading": "Laden",
"lock.unsaved": "Ungespeicherte Änderungen",
+ "lock.unsaved.empty": "Keine ungespeicherten Änderungen",
"lock.isLocked": "Ungespeicherte Änderungen von {email}",
"lock.file.isLocked": "Die Datei wird von {email} bearbeitet und kann nicht geändert werden.",
"lock.page.isLocked": "Die Seite wird von {email} bearbeitet und kann nicht geändert werden.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Veröffentlicht",
"pages.status.unlisted": "Ungelistet",
+ "pagination.page": "Seite",
+
"password": "Passwort",
"pixel": "Pixel",
"prev": "Vorheriger Eintrag",
@@ -384,6 +392,9 @@
"save": "Speichern",
"search": "Suchen",
+
+ "section.required": "Der Bereich ist Pflicht",
+
"select": "Auswählen",
"settings": "Einstellungen",
"size": "Größe",
diff --git a/i18n/translations/el.json b/i18n/translations/el.json
index 3eb8718ebb..1779e329b0 100644
--- a/i18n/translations/el.json
+++ b/i18n/translations/el.json
@@ -23,6 +23,7 @@
"delete": "\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae",
"dimensions": "Διαστάσεις",
+ "disabled": "Disabled",
"discard": "Απόρριψη",
"download": "Download",
"duplicate": "Duplicate",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Δεν ήταν δυνατή η φόρτωση της ενότητας \"{name}\"",
"error.section.type.invalid": "Ο τύπος ενότητας \"{type}\" δεν είναι έγκυρος",
+ "error.site.changeTitle.empty": "Ο τίτλος δεν μπορεί να είναι κενός",
"error.site.changeTitle.permission":
"Δεν επιτρέπεται να αλλάξετε τον τίτλο του ιστότοπου",
"error.site.update.permission": "Δεν επιτρέπεται η ενημέρωση του ιστότοπου",
@@ -155,6 +157,8 @@
"Ο ρόλος του τελευταίου διαχειριστή δεν μπορεί να αλλάξει",
"error.user.changeRole.permission":
"Δεν επιτρέπεται να αλλάξετε το ρόλο του χρήστη \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "Δεν επιτρέπεται η δημιουργία αυτού του χρήστη",
"error.user.delete": "\u039f \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 \u03b4\u03b5\u03bd \u03bc\u03c0\u03bf\u03c1\u03bf\u03cd\u03c3\u03b5 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03b5\u03af",
"error.user.delete.lastAdmin": "Δεν είναι δυνατή η διαγραφή του τελευταίου διαχειριστή",
@@ -219,6 +223,7 @@
"error.validation.time": "Παρακαλώ εισάγετε μια έγκυρη ώρα",
"error.validation.url": "Παρακαλώ εισάγετε μια έγκυρη διεύθυνση URL",
+ "field.required": "The field is required",
"field.files.empty": "Δεν έχουν επιλεγεί αρχεία ακόμα",
"field.pages.empty": "Δεν έχουν επιλεγεί ακόμη σελίδες",
"field.structure.delete.confirm": "\u0395\u03af\u03c3\u03c4\u03b5 \u03c3\u03af\u03b3\u03bf\u03c5\u03c1\u03bf\u03c2 \u03cc\u03c4\u03b9 \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03b5\u03c4\u03b5 \u03b1\u03c5\u03c4\u03ae\u03bd \u03c4\u03b7\u03bd \u03ba\u03b1\u03c4\u03b1\u03c7\u03ce\u03c1\u03b9\u03c3\u03b7;",
@@ -291,6 +296,7 @@
"loading": "Φόρτωση",
"lock.unsaved": "Unsaved changes",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Unsaved changes by {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Δημοσιευμένο",
"pages.status.unlisted": "Μη καταχωρημένο",
+ "pagination.page": "Σελίδα",
+
"password": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03a0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
"pixel": "Εικονοστοιχέιο",
"prev": "Προηγούμενο",
@@ -384,6 +392,9 @@
"save": "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7",
"search": "Αναζήτηση",
+
+ "section.required": "The section is required",
+
"select": "Επιλογή",
"settings": "Ρυθμίσεις",
"size": "Μέγεθος",
diff --git a/i18n/translations/en.json b/i18n/translations/en.json
index de88c92849..5249d4401b 100644
--- a/i18n/translations/en.json
+++ b/i18n/translations/en.json
@@ -23,6 +23,7 @@
"delete": "Delete",
"dimensions": "Dimensions",
+ "disabled": "Disabled",
"discard": "Discard",
"download": "Download",
"duplicate": "Duplicate",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "The section \"{name}\" could not be loaded",
"error.section.type.invalid": "The section type \"{type}\" is not valid",
+ "error.site.changeTitle.empty": "The title must not be empty",
"error.site.changeTitle.permission":
"You are not allowed to change the title of the site",
"error.site.update.permission": "You are not allowed to update the site",
@@ -221,6 +223,7 @@
"error.validation.time": "Please enter a valid time",
"error.validation.url": "Please enter a valid URL",
+ "field.required": "The field is required",
"field.files.empty": "No files selected yet",
"field.pages.empty": "No pages selected yet",
"field.structure.delete.confirm": "Do you really want to delete this row?",
@@ -293,6 +296,7 @@
"loading": "Loading",
"lock.unsaved": "Unsaved changes",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Unsaved changes by {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -366,6 +370,8 @@
"pages.status.listed": "Published",
"pages.status.unlisted": "Unlisted",
+ "pagination.page": "Page",
+
"password": "Password",
"pixel": "Pixel",
"prev": "Previous",
@@ -386,6 +392,9 @@
"save": "Save",
"search": "Search",
+
+ "section.required": "The section is required",
+
"select": "Select",
"settings": "Settings",
"size": "Size",
diff --git a/i18n/translations/es_419.json b/i18n/translations/es_419.json
index 305d611fae..6f28875c0a 100644
--- a/i18n/translations/es_419.json
+++ b/i18n/translations/es_419.json
@@ -23,6 +23,7 @@
"delete": "Eliminar",
"dimensions": "Dimensiones",
+ "disabled": "Disabled",
"discard": "Descartar",
"download": "Download",
"duplicate": "Duplicate",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "La sección \"{name}\" no se pudo cargar",
"error.section.type.invalid": "La sección \"{type}\" no es valida",
+ "error.site.changeTitle.empty": "El título no debe estar vacío.",
"error.site.changeTitle.permission":
"No tienes permiso para cambiar el título del sitio",
"error.site.update.permission": "No tienes permiso de actualizar el sitio",
@@ -155,6 +157,8 @@
"El rol del último administrador no puede ser cambiado",
"error.user.changeRole.permission":
"No tienes permiso para cambiar el rol del usuario \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "No tienes permiso de crear este usuario",
"error.user.delete": "El ususario no pudo ser eliminado",
"error.user.delete.lastAdmin": "Usted no puede borrar el \u00faltimo administrador",
@@ -219,6 +223,7 @@
"error.validation.time": "Por favor ingresa una hora válida",
"error.validation.url": "Por favor ingresa un URL válido",
+ "field.required": "The field is required",
"field.files.empty": "Aún no ha seleccionado ningún archivo",
"field.pages.empty": "Aún no ha seleccionado ningúna pagina",
"field.structure.delete.confirm": "\u00bfEn realidad desea borrar esta entrada?",
@@ -291,6 +296,7 @@
"loading": "Cargando",
"lock.unsaved": "Unsaved changes",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Unsaved changes by {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Publicado",
"pages.status.unlisted": "No publicado",
+ "pagination.page": "Página",
+
"password": "Contrase\u00f1a",
"pixel": "Pixel",
"prev": "Anterior",
@@ -384,6 +392,9 @@
"save": "Guardar",
"search": "Buscar",
+
+ "section.required": "The section is required",
+
"select": "Seleccionar",
"settings": "Ajustes",
"size": "Tamaño",
@@ -410,7 +421,7 @@
"translation.author": "Equipo Kirby",
"translation.direction": "ltr",
- "translation.name": "Inglés",
+ "translation.name": "Español (América Latina)",
"upload": "Subir",
"upload.error.cantMove": "The uploaded file could not be moved",
diff --git a/i18n/translations/es_ES.json b/i18n/translations/es_ES.json
index 8eff368de7..f70ed5a362 100644
--- a/i18n/translations/es_ES.json
+++ b/i18n/translations/es_ES.json
@@ -23,6 +23,7 @@
"delete": "Borrar",
"dimensions": "Dimensiones",
+ "disabled": "Disabled",
"discard": "Descartar",
"download": "Download",
"duplicate": "Duplicate",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "La sección \"{name}\" no pudo ser cargada",
"error.section.type.invalid": "El sección tipo \"{tipo}\" no es válido",
+ "error.site.changeTitle.empty": "El título no debe estar vacío.",
"error.site.changeTitle.permission":
"No está permitido cambiar el título del sitio",
"error.site.update.permission": "No tienes permitido actualizar el sitio",
@@ -155,6 +157,8 @@
"El rol para el último administrador no puede ser cambiado",
"error.user.changeRole.permission":
"No tienes permitido cambiar el rol del usuario \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "No tienes permiso para crear este usuario",
"error.user.delete": "El usuario \"{name}\" no puede ser eliminado",
"error.user.delete.lastAdmin": "El último administrador no puede ser eliminado",
@@ -219,6 +223,7 @@
"error.validation.time": "Por favor ingrese una hora válida",
"error.validation.url": "Por favor introduzca un URL válido",
+ "field.required": "The field is required",
"field.files.empty": "Aún no hay archivos seleccionados",
"field.pages.empty": "Aún no hay páginas seleccionadas",
"field.structure.delete.confirm": "¿Realmente quieres eliminar esta fila?",
@@ -291,6 +296,7 @@
"loading": "Cargando",
"lock.unsaved": "Unsaved changes",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Unsaved changes by {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Publicadas",
"pages.status.unlisted": "Sin publicar",
+ "pagination.page": "Página",
+
"password": "Contraseña",
"pixel": "Pixel",
"prev": "Anterior",
@@ -384,6 +392,9 @@
"save": "Guardar",
"search": "Buscar",
+
+ "section.required": "The section is required",
+
"select": "Seleccionar",
"settings": "Ajustes",
"size": "Tamaño",
diff --git a/i18n/translations/fa.json b/i18n/translations/fa.json
index f116961fa0..386f51b417 100644
--- a/i18n/translations/fa.json
+++ b/i18n/translations/fa.json
@@ -23,6 +23,7 @@
"delete": "\u062d\u0630\u0641",
"dimensions": "ابعاد",
+ "disabled": "Disabled",
"discard": "\u0627\u0646\u0635\u0631\u0627\u0641",
"download": "Download",
"duplicate": "Duplicate",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "بخش «{name}» قابل بارکذاری نیست",
"error.section.type.invalid": "نوع بخش «{type}» غیرمجاز است",
+ "error.site.changeTitle.empty": "عنوان اجباری است",
"error.site.changeTitle.permission":
"شما اجازه تغییر عنوان سایت را ندارید",
"error.site.update.permission": "شما اجازه بروزرسانی سایت را ندارید",
@@ -155,6 +157,8 @@
"نقش آخرین مدیر سیستم قابل تغییر نیست",
"error.user.changeRole.permission":
"شما اجازه تغییر نقش کاربر «{name}» را ندارید",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "شما اجازه ایجاد این کاربر را ندارید",
"error.user.delete": "کاربر «{name}» نمی تواند حذف شود",
"error.user.delete.lastAdmin": "\u062d\u0630\u0641 \u0622\u062e\u0631\u06cc\u0646 \u0645\u062f\u06cc\u0631 \u0633\u06cc\u0633\u062a\u0645 \u0645\u0645\u06a9\u0646 \u0646\u06cc\u0633\u062a",
@@ -219,6 +223,7 @@
"error.validation.time": "لطفا زمان معتبری وارد کنید",
"error.validation.url": "لطفا آدرس URL صحیح وارد کنید",
+ "field.required": "The field is required",
"field.files.empty": "فایلی انتخاب نشده است",
"field.pages.empty": "صفحهای انتخاب نشده است",
"field.structure.delete.confirm": "\u0645\u062f\u062e\u0644 \u062c\u0627\u0631\u06cc \u062d\u0630\u0641 \u0634\u0648\u062f\u061f",
@@ -291,6 +296,7 @@
"loading": "بارگزاری",
"lock.unsaved": "Unsaved changes",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Unsaved changes by {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -364,6 +370,8 @@
"pages.status.listed": "منتشر شده",
"pages.status.unlisted": "فهرست نشده",
+ "pagination.page": "صفحه",
+
"password": "\u06af\u0630\u0631\u0648\u0627\u0698\u0647",
"pixel": "پیکسل",
"prev": "قبلی",
@@ -384,6 +392,9 @@
"save": "\u0630\u062e\u06cc\u0631\u0647",
"search": "جستجو",
+
+ "section.required": "The section is required",
+
"select": "انتخاب",
"settings": "تنظیمات",
"size": "اندازه",
diff --git a/i18n/translations/fi.json b/i18n/translations/fi.json
index 2c38093b57..be3f4aa8f7 100644
--- a/i18n/translations/fi.json
+++ b/i18n/translations/fi.json
@@ -23,21 +23,22 @@
"delete": "Poista",
"dimensions": "Mitat",
+ "disabled": "Disabled",
"discard": "Hylkää",
- "download": "Download",
- "duplicate": "Duplicate",
+ "download": "Lataa",
+ "duplicate": "Kahdenna",
"edit": "Muokkaa",
- "dialog.files.empty": "No files to select",
- "dialog.pages.empty": "No pages to select",
- "dialog.users.empty": "No users to select",
+ "dialog.files.empty": "Ei valittavissa olevia tiedostoja",
+ "dialog.pages.empty": "Ei valittavissa olevia sivuja",
+ "dialog.users.empty": "Ei valittavissa olevia käyttäjiä",
"email": "S\u00e4hk\u00f6posti",
"email.placeholder": "nimi@osoite.fi",
"error.access.login": "Kirjautumistiedot eivät kelpaa",
"error.access.panel": "Sinulla ei ole oikeutta käyttää paneelia",
- "error.access.view": "You are not allowed to access this part of the panel",
+ "error.access.view": "Sinulla ei ole oikeutta käyttää tätä osaa paneelista",
"error.avatar.create.fail": "Profiilikuvaa ei voitu lähettää",
"error.avatar.delete.fail": "Profiilikuvaa ei voitu poistaa",
@@ -52,7 +53,7 @@
"error.field.converter.invalid": "Muunnin \"{converter}\" ei kelpaa",
- "error.file.changeName.empty": "The name must not be empty",
+ "error.file.changeName.empty": "Nimi ei voi olla tyhjä",
"error.file.changeName.permission":
"Sinulla ei ole oikeutta muuttaa tiedoston \"{filename}\" nimeä",
"error.file.duplicate": "Tiedosto nimellä \"{filename}\" on jo olemassa",
@@ -73,13 +74,13 @@
"error.form.incomplete": "Korjaa kaikki lomakkeen virheet...",
"error.form.notSaved": "Lomaketta ei voitu tallentaa",
- "error.language.code": "Please enter a valid code for the language",
- "error.language.duplicate": "The language already exists",
- "error.language.name": "Please enter a valid name for the language",
+ "error.language.code": "Anna kielen lyhenne",
+ "error.language.duplicate": "Kieli on jo olemassa",
+ "error.language.name": "Anna kielen nimi",
- "error.license.format": "Please enter a valid license key",
+ "error.license.format": "Anna lisenssiavain",
"error.license.email": "Anna kelpaava sähköpostiosoite",
- "error.license.verification": "The license could not be verified",
+ "error.license.verification": "Lisenssiä ei voitu vahvistaa",
"error.page.changeSlug.permission":
"Sinulla ei ole oikeutta muuttaa URL-liitettä sivulle \"{slug}\"",
@@ -106,7 +107,7 @@
"Sivuluonnos URL-liitteellä \"{slug}\" on jo olemassa",
"error.page.duplicate":
"Sivu URL-liitteellä \"{slug}\" on jo olemassa",
- "error.page.duplicate.permission": "You are not allowed to duplicate \"{slug}\"",
+ "error.page.duplicate.permission": "Sinulla ei ole oikeutta kahdentaa sivua \"{slug}\"",
"error.page.notFound": "Sivua \"{slug}\" ei löytynyt",
"error.page.num.invalid":
"Anna kelpaava järjestysnumero. Numero ei voi olla negatiivinen.",
@@ -121,22 +122,23 @@
"error.section.files.max.singular":
"Et voi lisätä enempää kuin yhden tiedoston osioon \"{section}\"",
"error.section.files.min.plural":
- "The \"{section}\" section requires at least {min} files",
+ "Osio \"{section}\" vaatii ainakin {min} tiedostoa",
"error.section.files.min.singular":
- "The \"{section}\" section requires at least one file",
+ "Osio \"{section}\" vaatii ainakin yhden sivun",
"error.section.pages.max.plural":
"Et voi lisätä enemmän kuin {max} sivua osioon \"{section}\"",
"error.section.pages.max.singular":
"Et voi lisätä enempää kuin yhden sivun osioon \"{section}\"",
"error.section.pages.min.plural":
- "The \"{section}\" section requires at least {min} pages",
+ "Osio \"{section}\" vaatii ainakin {min} sivua",
"error.section.pages.min.singular":
- "The \"{section}\" section requires at least one page",
+ "Osio \"{section}\" vaatii ainakin yhden sivun",
"error.section.notLoaded": "Osiota \"{name}\" ei voitu ladata",
"error.section.type.invalid": "Osion tyyppi \"{type}\" ei ole kelvollinen",
+ "error.site.changeTitle.empty": "Nimi ei voi olla tyhjä",
"error.site.changeTitle.permission":
"Sinulla ei ole oikeutta päivittää sivuston nimeä",
"error.site.update.permission": "Sinulla ei ole oikeutta päivittää sivuston tietoja",
@@ -152,17 +154,19 @@
"error.user.changePassword.permission":
"Sinulla ei ole oikeutta vaihtaa käyttäjän \"{name}\" salasanaa",
"error.user.changeRole.lastAdmin":
- "Ainoan ylläpitäjän roolia ei voi muuttaa",
+ "Ainoan pääkäyttäjän roolia ei voi muuttaa",
"error.user.changeRole.permission":
"Sinulla ei ole oikeutta vaihtaa käyttäjän \"{name}\" käyttäjätasoa",
+ "error.user.changeRole.toAdmin":
+ "Sinulla ei ole oikeutta vaihtaa käyttäjätasoa pääkäyttäjäksi",
"error.user.create.permission": "Sinulla ei ole oikeutta luoda tätä käyttäjää",
"error.user.delete": "Käyttäjää \"{name}\" ei voi poistaa",
- "error.user.delete.lastAdmin": "Ainoaa ylläpitäjää ei voi poistaa",
+ "error.user.delete.lastAdmin": "Ainoaa pääkäyttäjää ei voi poistaa",
"error.user.delete.lastUser": "Ainoaa käyttäjää ei voi poistaa",
"error.user.delete.permission":
"Sinulla ei ole oikeutta poistaa käyttäjää \"{name}\"",
"error.user.duplicate":
- "Käyttäjä jonka sähköpostiosoite on \"{name}\" on jo olemassa",
+ "Käyttäjä, jonka sähköpostiosoite on \"{name}\", on jo olemassa",
"error.user.email.invalid": "Anna kelpaava sähköpostiosoite",
"error.user.language.invalid": "Anna kelpaava kieli",
"error.user.notFound": "K\u00e4ytt\u00e4j\u00e4\u00e4 ei l\u00f6ytynyt",
@@ -184,9 +188,9 @@
"error.validation.contains":
"Anna arvo joka sisältää \"{needle}\"",
"error.validation.date": "Anna kelpaava päivämäärä",
- "error.validation.date.after": "Please enter a date after {date}",
- "error.validation.date.before": "Please enter a date before {date}",
- "error.validation.date.between": "Please enter a date between {min} and {max}",
+ "error.validation.date.after": "Anna päivämäärä {date} jälkeen",
+ "error.validation.date.before": "Anna päivämäärä ennen {date}",
+ "error.validation.date.between": "Anna päivämäärä väliltä {min} ja {max}",
"error.validation.denied": "Ole hyvä ja peruuta",
"error.validation.different": "Arvo ei voi olla \"{other}\"",
"error.validation.email": "Anna kelpaava sähköpostiosoite",
@@ -219,6 +223,7 @@
"error.validation.time": "Anna kelpaava aika",
"error.validation.url": "Anna kelpaava URL",
+ "field.required": "Kenttä on pakollinen",
"field.files.empty": "Tiedostoja ei ole vielä valittu",
"field.pages.empty": " Sivuja ei ole vielä valittu",
"field.structure.delete.confirm": "Haluatko varmasti poistaa tämän rivin?",
@@ -290,11 +295,12 @@
"loading": "Ladataan",
- "lock.unsaved": "Unsaved changes",
- "lock.isLocked": "Unsaved changes by {email}",
+ "lock.unsaved": "Tallentamattomia muutoksia",
+ "lock.unsaved.empty": "There are no more unsaved changes",
+ "lock.isLocked": "Käyttäjällä {email} on tallentamattomia muutoksia",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
- "lock.unlock": "Unlock",
+ "lock.unlock": "Vapauta",
"lock.isUnlocked": "Your unsaved changes have been overwritten by another user. You can download your changes to merge them manually.",
"login": "Kirjaudu",
@@ -364,6 +370,8 @@
"pages.status.listed": "Julkaistut",
"pages.status.unlisted": "Listaamaton",
+ "pagination.page": "Sivu",
+
"password": "Salasana",
"pixel": "Pikseli",
"prev": "Edellinen",
@@ -374,8 +382,8 @@
"revert": "Palauta",
"role": "K\u00e4ytt\u00e4j\u00e4taso",
- "role.admin.description": "The admin has all rights",
- "role.admin.title": "Admin",
+ "role.admin.description": "Pääkäyttäjällä on kaikki oikeudet",
+ "role.admin.title": "Pääkäyttäjä",
"role.all": "Kaikki",
"role.empty": "Tällä käyttäjätasolla ei ole yhtään käyttäjää",
"role.description.placeholder": "Ei kuvausta",
@@ -384,6 +392,9 @@
"save": "Tallenna",
"search": "Haku",
+
+ "section.required": "Osio on pakollinen",
+
"select": "Valitse",
"settings": "Asetukset",
"size": "Koko",
@@ -413,15 +424,15 @@
"translation.name": "Suomi",
"upload": "Lähetä",
- "upload.error.cantMove": "The uploaded file could not be moved",
- "upload.error.cantWrite": "Failed to write file to disk",
- "upload.error.default": "The file could not be uploaded",
+ "upload.error.cantMove": "Lähetettyä tiedostoa ei voitu siirtää",
+ "upload.error.cantWrite": "Tiedoston kirjoitus levylle epäonnistui",
+ "upload.error.default": "Tiedostoa ei voitu lähettää",
"upload.error.extension": "File upload stopped by extension",
- "upload.error.formSize": "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the form",
- "upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
- "upload.error.iniSize": "The uploaded file exceeds the upload_max_filesize directive in php.ini",
- "upload.error.noFile": "No file was uploaded",
- "upload.error.noFiles": "No files were uploaded",
+ "upload.error.formSize": "Lähetetyn tiedoston koko ylittää lomakkeen sallitun ylärajan MAX_FILE_SIZE",
+ "upload.error.iniPostSize": "Lähetetyn tiedoston koko ylittää sallitun ylärajan post_max_size asetustiedostossa php.ini",
+ "upload.error.iniSize": "Lähetetyn tiedoston koko ylittää sallitun ylärajan upload_max_filesize asetustiedostossa php.ini",
+ "upload.error.noFile": "Tiedostoa ei lähetetty",
+ "upload.error.noFiles": "Tiedostoja ei lähetetty",
"upload.error.partial": "The uploaded file was only partially uploaded",
"upload.error.tmpDir": "Missing a temporary folder",
"upload.errors": "Virhe",
diff --git a/i18n/translations/fr.json b/i18n/translations/fr.json
index 93c19e4b4b..215f05271a 100644
--- a/i18n/translations/fr.json
+++ b/i18n/translations/fr.json
@@ -23,6 +23,7 @@
"delete": "Supprimer",
"dimensions": "Dimensions",
+ "disabled": "Désactivé",
"discard": "Supprimer",
"download": "Télécharger",
"duplicate": "Dupliquer",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "La section « {name} » n’a pu être chargée",
"error.section.type.invalid": "Le type de section « {type} » est incorrect",
+ "error.site.changeTitle.empty": "Le titre ne peut être vide",
"error.site.changeTitle.permission":
"Vous n’êtes pas autorisé à modifier le titre du site",
"error.site.update.permission": "Vous n’êtes pas autorisé à modifier le contenu global du site",
@@ -155,6 +157,8 @@
"Le rôle du dernier administrateur ne peut être modifié",
"error.user.changeRole.permission":
"Vous n’êtes pas autorisé à changer le rôle de l’utilisateur « {name} »",
+ "error.user.changeRole.toAdmin":
+ "Vous n’êtes pas autorisé à attribuer le rôle d’administrateur aux utilisateurs",
"error.user.create.permission": "Vous n’êtes pas autorisé à créer cet utilisateur",
"error.user.delete": "L’utilisateur « {name} » ne peut être supprimé",
"error.user.delete.lastAdmin": "Le dernier administrateur ne peut être supprimé",
@@ -219,6 +223,7 @@
"error.validation.time": "Veuillez saisir une heure valide",
"error.validation.url": "Veuillez saisir une URL valide",
+ "field.required": "Le champ est obligatoire",
"field.files.empty": "Pas encore de fichier sélectionné",
"field.pages.empty": "Pas encore de page sélectionnée",
"field.structure.delete.confirm": "Voulez-vous vraiment supprimer cette ligne?",
@@ -291,6 +296,7 @@
"loading": "Chargement",
"lock.unsaved": "Modifications non enregistrées",
+ "lock.unsaved.empty": "Il n’y a plus de modifications non enregistrées",
"lock.isLocked": "Modifications non enregistrées par {email}",
"lock.file.isLocked": "Le fichier est actuellement édité par {email} et ne peut être modifié.",
"lock.page.isLocked": "La page est actuellement éditée par {email} et ne peut être modifiée.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Publié",
"pages.status.unlisted": "Non listé",
+ "pagination.page": "Page",
+
"password": "Mot de passe",
"pixel": "Pixel",
"prev": "Précédent",
@@ -384,6 +392,9 @@
"save": "Enregistrer",
"search": "Rechercher",
+
+ "section.required": "Cette section est obligatoire",
+
"select": "Sélectionner",
"settings": "Paramètres",
"size": "Poids",
@@ -418,8 +429,8 @@
"upload.error.default": "Le fichier n’a pu être transféré",
"upload.error.extension": "Le transfert de fichier a été stoppé par une extension",
"upload.error.formSize": "Le fichier transféré excède la directive MAX_FILE_SIZE spécifiée dans le formulaire",
- "upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
- "upload.error.iniSize": "Le fichier transféré excède la directive MAX_FILE_SIZE spécifiée dans php.ini",
+ "upload.error.iniPostSize": "Le fichier transféré excède la directive post_max_size spécifiée dans php.ini",
+ "upload.error.iniSize": "Le fichier transféré excède la directive upload_max_filesize spécifiée dans php.ini",
"upload.error.noFile": "Aucun fichier n’a été transféré",
"upload.error.noFiles": "Aucun fichier n’a été transféré",
"upload.error.partial": "Le fichier n’a été que partiellement transféré",
diff --git a/i18n/translations/hu.json b/i18n/translations/hu.json
index 85534a321b..caf35dfd8d 100644
--- a/i18n/translations/hu.json
+++ b/i18n/translations/hu.json
@@ -23,6 +23,7 @@
"delete": "T\u00f6rl\u00e9s",
"dimensions": "Méretek",
+ "disabled": "Disabled",
"discard": "Visszavon\u00e1s",
"download": "Letöltés",
"duplicate": "Másolat",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "A(z) \"{name}\" szekció nem tölthető be",
"error.section.type.invalid": "A szekció típusa (\"{type}\") nem megfelelő",
+ "error.site.changeTitle.empty": "A cím nem lehet üres",
"error.site.changeTitle.permission":
"Nincs jogosultságod megváltoztatni az honlap címét",
"error.site.update.permission": "Nincs jogosultságod frissíteni a honlapot",
@@ -155,6 +157,8 @@
"Az egyedüli adminisztrátor szerepkörét nem lehet megváltoztatni",
"error.user.changeRole.permission":
"Nincs jogosultságod megváltoztatni \"{name}\" felhasználó szerepkörét",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "Nincs jogosultságod létrehozni ezt a felhasználót",
"error.user.delete": "A felhaszn\u00e1l\u00f3 nem t\u00f6r\u00f6lhet\u0151",
"error.user.delete.lastAdmin": "Nem t\u00f6r\u00f6lheted az egyetlen adminisztr\u00e1tort",
@@ -219,6 +223,7 @@
"error.validation.time": "Kérlek megfelelő időt adj meg",
"error.validation.url": "Kérlek megfelelő URL-t adj meg",
+ "field.required": "The field is required",
"field.files.empty": "Nincs fálj kiválasztva",
"field.pages.empty": "Nincs oldal kiválasztva",
"field.structure.delete.confirm": "Biztos t\u00f6r\u00f6lni szeretn\u00e9d ezt a bejegyz\u00e9st?",
@@ -291,6 +296,7 @@
"loading": "Betöltés",
"lock.unsaved": "Nem mentett változások",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Nem mentett {email} változások",
"lock.file.isLocked": "A fájlt jelenleg {email} szerkeszti és nem módosítható.",
"lock.page.isLocked": "Az oldalt jelenleg {email} szerkeszti és nem módosítható.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Publikálva",
"pages.status.unlisted": "Nem listázott",
+ "pagination.page": "Oldal",
+
"password": "Jelsz\u00f3",
"pixel": "Pixel",
"prev": "Előző",
@@ -384,6 +392,9 @@
"save": "Ment\u00e9s",
"search": "Keresés",
+
+ "section.required": "The section is required",
+
"select": "Kiválasztás",
"settings": "Beállítások",
"size": "Méret",
diff --git a/i18n/translations/id.json b/i18n/translations/id.json
index 6931b2eb4f..ccb6b276a8 100644
--- a/i18n/translations/id.json
+++ b/i18n/translations/id.json
@@ -23,6 +23,7 @@
"delete": "Hapus",
"dimensions": "Dimensi",
+ "disabled": "Dimatikan",
"discard": "Buang",
"download": "Unduh",
"duplicate": "Duplikasi",
@@ -37,7 +38,7 @@
"error.access.login": "Upaya masuk tidak valid",
"error.access.panel": "Anda tidak diizinkan mengakses panel",
- "error.access.view": "You are not allowed to access this part of the panel",
+ "error.access.view": "Anda tidak diizinkan mengakses bagian panel ini",
"error.avatar.create.fail": "Gambar profil tidak dapat diunggah",
"error.avatar.delete.fail": "Gambar profil tidak dapat dihapus",
@@ -52,7 +53,7 @@
"error.field.converter.invalid": "Konverter \"{converter}\" tidak valid",
- "error.file.changeName.empty": "The name must not be empty",
+ "error.file.changeName.empty": "Nama harus diisi",
"error.file.changeName.permission":
"Anda tidak diizinkan mengubah nama berkas \"{filename}\"",
"error.file.duplicate": "Berkas dengan nama \"{filename}\" sudah ada",
@@ -65,7 +66,7 @@
"error.file.mime.forbidden": "Media dengan tipe mime \"{mime}\" tidak diizinkan",
"error.file.mime.missing":
"Tipe media untuk \"{filename}\" tidak dapat dideteksi",
- "error.file.name.missing": "Nama berkas tidak boleh kosong",
+ "error.file.name.missing": "Nama berkas harus diisi",
"error.file.notFound": "Berkas \"{filename}\" tidak dapat ditemukan",
"error.file.type.forbidden": "Anda tidak diizinkan mengunggah berkas dengan tipe {type}",
"error.file.undefined": "Berkas tidak dapat ditemukan",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Bagian \"{name}\" tidak dapat dimuat",
"error.section.type.invalid": "Tipe bagian \"{type}\" tidak valid",
+ "error.site.changeTitle.empty": "Judul harus diisi",
"error.site.changeTitle.permission":
"Anda tidak diizinkan mengubah judul situs",
"error.site.update.permission": "Anda tidak diizinkan memperbaharui situs",
@@ -155,6 +157,8 @@
"Peran dari admin satu-satunya tidak dapat diubah",
"error.user.changeRole.permission":
"Anda tidak diizinkan mengubah peran dari pengguna \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "Anda tidak diizinkan mempromosikan seseorang menjadi admin",
"error.user.create.permission": "Anda tidak diizinkan membuat pengguna ini",
"error.user.delete": "Pengguna \"{nama}\" tidak dapat dihapus",
"error.user.delete.lastAdmin": "Admin satu-satunya tidak dapat dihapus",
@@ -219,6 +223,7 @@
"error.validation.time": "Masukkan waktu yang valid",
"error.validation.url": "Masukkan URL yang valid",
+ "field.required": "Bidang ini wajib",
"field.files.empty": "Belum ada berkas yang dipilih",
"field.pages.empty": "Belum ada halaman yang dipilih",
"field.structure.delete.confirm": "Anda yakin menghapus baris ini?",
@@ -291,6 +296,7 @@
"loading": "Memuat",
"lock.unsaved": "Perubahan belum tersimpan",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Perubahan belum tersimpan oleh {email}",
"lock.file.isLocked": "Berkas sedang disunting oleh {email} dan tidak dapat diubah.",
"lock.page.isLocked": "Halaman sedang disunting oleh {email} dan tidak dapat diubah.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Dipublikasikan",
"pages.status.unlisted": "Tidak tercantum",
+ "pagination.page": "Halaman",
+
"password": "Sandi",
"pixel": "Piksel",
"prev": "Sebelumnya",
@@ -384,6 +392,9 @@
"save": "Simpan",
"search": "Cari",
+
+ "section.required": "Bagian ini wajib",
+
"select": "Pilih",
"settings": "Pengaturan",
"size": "Ukuran",
@@ -413,17 +424,17 @@
"translation.name": "Bahasa Indonesia",
"upload": "Unggah",
- "upload.error.cantMove": "The uploaded file could not be moved",
- "upload.error.cantWrite": "Failed to write file to disk",
- "upload.error.default": "The file could not be uploaded",
- "upload.error.extension": "File upload stopped by extension",
- "upload.error.formSize": "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the form",
- "upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
- "upload.error.iniSize": "The uploaded file exceeds the upload_max_filesize directive in php.ini",
- "upload.error.noFile": "No file was uploaded",
- "upload.error.noFiles": "No files were uploaded",
- "upload.error.partial": "The uploaded file was only partially uploaded",
- "upload.error.tmpDir": "Missing a temporary folder",
+ "upload.error.cantMove": "Berkas unggahan tidak dapat dipindahkan",
+ "upload.error.cantWrite": "Gagal menyimpan berkas",
+ "upload.error.default": "Berkas tidak dapat diunggah",
+ "upload.error.extension": "Unggahan berkas diblokir dengan ekstensi",
+ "upload.error.formSize": "Berkas unggahan mencapai acuan MAX_FILE_SIZE yang diatur di formulir",
+ "upload.error.iniPostSize": "Berkas unggahan mencapai acuan post_max_size di php.ini",
+ "upload.error.iniSize": "Berkas unggahan mencapai acuan upload_max_filesize di php.ini",
+ "upload.error.noFile": "Tidak ada berkas diunggah",
+ "upload.error.noFiles": "Tidak ada berkas diunggah",
+ "upload.error.partial": "Berkas unggahan hanya berhasil diunggah sebagian",
+ "upload.error.tmpDir": "Folder sementara tidak ada",
"upload.errors": "Kesalahan",
"upload.progress": "Mengunggah…",
diff --git a/i18n/translations/it.json b/i18n/translations/it.json
index 30dffa9414..31ac283d7d 100644
--- a/i18n/translations/it.json
+++ b/i18n/translations/it.json
@@ -23,6 +23,7 @@
"delete": "Elimina",
"dimensions": "Dimensioni",
+ "disabled": "Disabled",
"discard": "Abbandona",
"download": "Scarica",
"duplicate": "Duplica",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Non è stato possibile caricare la sezione \"{name}\"",
"error.section.type.invalid": "Il tipo di sezione \"{type}\" non è valido",
+ "error.site.changeTitle.empty": "Il titolo non può essere vuoto",
"error.site.changeTitle.permission":
"Non ti è permesso modificare il titolo del sito",
"error.site.update.permission": "Non ti è permesso modificare i contenuti globali del sito",
@@ -155,6 +157,8 @@
"Il ruolo dell'ultimo amministratore non può esser cambiato",
"error.user.changeRole.permission":
"Non ti è permesso modificare il ruolo dell'utente \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "Non ti è permesso creare questo utente",
"error.user.delete": "L'utente non pu\u00f2 essere eliminato",
"error.user.delete.lastAdmin": "L'ultimo amministratore non può essere eliminato",
@@ -219,6 +223,7 @@
"error.validation.time": "Inserisci un orario valido",
"error.validation.url": "Inserisci un URL valido",
+ "field.required": "The field is required",
"field.files.empty": "Nessun file selezionato",
"field.pages.empty": "Nessuna pagina selezionata",
"field.structure.delete.confirm": "Vuoi veramente eliminare questo elemento?",
@@ -291,6 +296,7 @@
"loading": "Caricamento",
"lock.unsaved": "Modifiche non salvate",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Modifiche non salvate di {email}",
"lock.file.isLocked": "Il file viene attualmente modificato da {email} e non può essere cambiato.",
"lock.page.isLocked": "la pagina viene attualmente modificata da {email} e non può essere cambiata.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Pubblicato",
"pages.status.unlisted": "Non in elenco",
+ "pagination.page": "Pagina",
+
"password": "Password",
"pixel": "Pixel",
"prev": "Precedente",
@@ -384,6 +392,9 @@
"save": "Salva",
"search": "Cerca",
+
+ "section.required": "The section is required",
+
"select": "Seleziona",
"settings": "Impostazioni",
"size": "Dimensioni",
diff --git a/i18n/translations/ko.json b/i18n/translations/ko.json
index 8092ac6fca..e4fa56ea45 100644
--- a/i18n/translations/ko.json
+++ b/i18n/translations/ko.json
@@ -23,26 +23,27 @@
"delete": "\uc0ad\uc81c",
"dimensions": "크기",
+ "disabled": "비활성화",
"discard": "무시",
"download": "다운로드",
"duplicate": "복제",
"edit": "\ud3b8\uc9d1",
- "dialog.files.empty": "No files to select",
- "dialog.pages.empty": "No pages to select",
- "dialog.users.empty": "No users to select",
+ "dialog.files.empty": "선택된 파일이 없습니다.",
+ "dialog.pages.empty": "선택된 페이지가 없습니다.",
+ "dialog.users.empty": "선택된 사용자가 없습니다.",
"email": "\uc774\uba54\uc77c \uc8fc\uc18c",
"email.placeholder": "mail@example.com",
"error.access.login": "로그인할 수 없습니다.",
"error.access.panel": "패널에 접근할 권한이 없습니다.",
- "error.access.view": "You are not allowed to access this part of the panel",
+ "error.access.view": "패널에 접근할 권한이 없습니다.",
"error.avatar.create.fail": "프로필 이미지를 업로드할 수 없습니다.",
"error.avatar.delete.fail": "\ud504\ub85c\ud544 \uc774\ubbf8\uc9c0\ub97c \uc0ad\uc81c\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.",
"error.avatar.dimensions.invalid":
- "프로필 이미지의 크기를 가로세로 3,000픽셀 이하로 설정하세요.",
+ "프로필 이미지의 크기를 3,000픽셀 이하로 설정하세요.",
"error.avatar.mime.forbidden":
"\uc5c5\ub85c\ub4dc\ud560 \uc218 \uc5c6\ub294 MIME \ud615\uc2dd\uc785\ub2c8\ub2e4.",
@@ -52,7 +53,7 @@
"error.field.converter.invalid": "컨버터({converter})가 올바르지 않습니다.",
- "error.file.changeName.empty": "The name must not be empty",
+ "error.file.changeName.empty": "이름을 입력하세요.",
"error.file.changeName.permission":
"파일명({filename})을 변경할 권한이 없습니다.",
"error.file.duplicate": "파일명이 같은 파일({filename})이 있습니다.",
@@ -73,9 +74,9 @@
"error.form.incomplete": "항목에 오류가 있습니다.",
"error.form.notSaved": "항목을 저장할 수 없습니다.",
- "error.language.code": "Please enter a valid code for the language",
- "error.language.duplicate": "The language already exists",
- "error.language.name": "올바른 언어를 입력하세요.",
+ "error.language.code": "올바른 언어 코드를 입력하세요.",
+ "error.language.duplicate": "이미 등록된 언어입니다.",
+ "error.language.name": "올바른 언어명을 입력하세요.",
"error.license.format": "올바른 라이선스 키를 입력하세요.",
"error.license.email": "올바른 이메일 주소를 입력하세요.",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "섹션({name})을 불러올 수 없습니다.",
"error.section.type.invalid": "섹션의 형식({type})이 올바르지 않습니다.",
+ "error.site.changeTitle.empty": "제목을 입력하세요.",
"error.site.changeTitle.permission":
"사이트명을 변경할 권한이 없습니다.",
"error.site.update.permission": "사이트의 정보를 변경할 권한이 없습니다.",
@@ -155,6 +157,8 @@
"최종 관리자의 역할은 변경할 수 없습니다.",
"error.user.changeRole.permission":
"사용자({name})의 역할을 변경할 권한이 없습니다.",
+ "error.user.changeRole.toAdmin":
+ "다른 사용자를 관리자로 지정할 권한이 없습니다.",
"error.user.create.permission": "사용자를 등록할 권한이 없습니다.",
"error.user.delete": "사용자({name})를 삭제할 수 없습니다.",
"error.user.delete.lastAdmin": "\ucd5c\uc885 \uad00\ub9ac\uc790\ub294 \uc0ad\uc81c\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.",
@@ -184,9 +188,9 @@
"error.validation.contains":
"{needle}에 포함된 값을 입력하세요.",
"error.validation.date": "올바른 날짜를 입력하세요.",
- "error.validation.date.after": "Please enter a date after {date}",
- "error.validation.date.before": "Please enter a date before {date}",
- "error.validation.date.between": "Please enter a date between {min} and {max}",
+ "error.validation.date.after": "{date} 이후 날짜를 입력하세요.",
+ "error.validation.date.before": "{date} 이전 날짜를 입력하세요.",
+ "error.validation.date.between": "{min}, {max} 사이의 날짜를 입력하세요.",
"error.validation.denied": "취소하세요.",
"error.validation.different": "{other}에 포함된 값은 입력할 수 없습니다.",
"error.validation.email": "올바른 이메일 주소를 입력하세요.",
@@ -219,6 +223,7 @@
"error.validation.time": "올바른 시간을 입력하세요.",
"error.validation.url": "올바른 URL을 입력하세요.",
+ "field.required": "필드가 필요합니다.",
"field.files.empty": "선택된 파일이 없습니다.",
"field.pages.empty": "선택된 페이지가 없습니다.",
"field.structure.delete.confirm": "이 행을 삭제할까요?",
@@ -254,7 +259,7 @@
"installation.issues.sessions": "폴더(/site/sessions)에 쓰기 권한이 없습니다.",
"language": "\uc5b8\uc5b4",
- "language.code": "코드",
+ "language.code": "언어 코드",
"language.convert": "기본 언어로 설정",
"language.convert.confirm":
"이 언어({name})를 기본 언어로 설정할까요? 설정한 뒤에는 복원할 수 없습니다. 번역되지 않은 항목은 올바르게 표시되지 않을 수 있습니다.",
@@ -266,7 +271,7 @@
"language.direction.ltr": "왼쪽에서 오른쪽",
"language.direction.rtl": "오른쪽에서 왼쪽",
"language.locale": "PHP 로캘 문자열",
- "language.locale.warning": "You are using a custom locale set up. Please modify it in the language file in /site/languages",
+ "language.locale.warning": "커스텀 언어 설정를 사용 중입니다. /site/languages 폴더의 언어 파일을 수정하세요.",
"language.name": "이름",
"language.updated": "언어를 변경했습니다.",
@@ -280,7 +285,7 @@
"license.buy": "라이선스 구매",
"license.register": "등록",
"license.register.help":
- "입력한 이메일 주소로 라이선스 코드를 전송합니다. Kirby를 등록하려면 라이선스 코드를 입력하세요.",
+ "이메일 주소로 라이선스 코드를 전송했습니다. Kirby를 등록하려면 라이선스 코드와 이메일 주소를 입력하세요.",
"license.register.label": "라이선스 코드를 입력하세요.",
"license.register.success": "Kirby를 구입해주셔서 감사합니다.",
"license.unregistered": "Kirby가 등록되지 않았습니다.",
@@ -291,11 +296,12 @@
"loading": "로딩 중",
"lock.unsaved": "수정 사항이 저장되지 않았습니다.",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "{email}의 수정 사항이 저장되지 않았습니다.",
"lock.file.isLocked": "다른 사용자({email})가 수정 중입니다.",
"lock.page.isLocked": "다른 사용자({email}가 수정 중입니다.",
"lock.unlock": "잠금",
- "lock.isUnlocked": "Your unsaved changes have been overwritten by another user. You can download your changes to merge them manually.",
+ "lock.isUnlocked": "다른 사용자가 내용을 수정했으므로 내용이 저장되지 않았습니다. 저장되지 않은 내용을 내려받아 수동으로 대치할 수 있습니다.",
"login": "\ub85c\uadf8\uc778",
"login.remember": "로그인 유지",
@@ -364,6 +370,8 @@
"pages.status.listed": "발행",
"pages.status.unlisted": "비공개",
+ "pagination.page": "페이지",
+
"password": "\uc554\ud638",
"pixel": "픽셀",
"prev": "이전",
@@ -374,16 +382,19 @@
"revert": "복원",
"role": "역할",
- "role.admin.description": "The admin has all rights",
+ "role.admin.description": "관리자는 모든 권한이 있습니다.",
"role.admin.title": "관리자",
"role.all": "전체 보기",
"role.empty": "이 역할에 해당하는 사용자가 없습니다.",
"role.description.placeholder": "설명이 없습니다.",
- "role.nobody.description": "This is a fallback role without any permissions",
- "role.nobody.title": "Nobody",
+ "role.nobody.description": "대체 사용자는 어떤 권한도 없습니다.",
+ "role.nobody.title": "사용자가 없습니다.",
"save": "\uc800\uc7a5",
"search": "검색",
+
+ "section.required": "섹션이 필요합니다.",
+
"select": "선택",
"settings": "설정",
"size": "크기",
@@ -413,17 +424,17 @@
"translation.name": "한국어",
"upload": "업로드",
- "upload.error.cantMove": "The uploaded file could not be moved",
- "upload.error.cantWrite": "Failed to write file to disk",
- "upload.error.default": "The file could not be uploaded",
- "upload.error.extension": "File upload stopped by extension",
+ "upload.error.cantMove": "업로드한 파일을 이동할 수 없습니다.",
+ "upload.error.cantWrite": "디스크를 읽을 수 없습니다.",
+ "upload.error.default": "파일을 업로드할 수 없습니다.",
+ "upload.error.extension": "파일 확장자를 다시 한번 확인하세요.",
"upload.error.formSize": "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the form",
"upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
"upload.error.iniSize": "The uploaded file exceeds the upload_max_filesize directive in php.ini",
- "upload.error.noFile": "No file was uploaded",
- "upload.error.noFiles": "No files were uploaded",
- "upload.error.partial": "The uploaded file was only partially uploaded",
- "upload.error.tmpDir": "Missing a temporary folder",
+ "upload.error.noFile": "업로드된 파일이 없습니다.",
+ "upload.error.noFiles": "업로드된 파일이 없습니다.",
+ "upload.error.partial": "일부 파일만 업로드했습니다.",
+ "upload.error.tmpDir": "임시 폴더가 없습니다.",
"upload.errors": "오류",
"upload.progress": "업로드 중…",
@@ -432,7 +443,7 @@
"user": "사용자",
"user.blueprint":
- "/site/blueprints/users/{role}.yml 파일에 옵션을 추가할 수 있습니다.",
+ "/site/blueprints/users/{role}.yml 파일에 섹션 및 폼 필드를 추가할 수 있습니다.",
"user.changeEmail": "이메일 주소 변경",
"user.changeLanguage": "언어 변경",
"user.changeName": "사용자명 변경",
diff --git a/i18n/translations/lt.json b/i18n/translations/lt.json
index f9e3db0969..4eb3a7b2a3 100644
--- a/i18n/translations/lt.json
+++ b/i18n/translations/lt.json
@@ -23,6 +23,7 @@
"delete": "Pašalinti",
"dimensions": "Išmatavimai",
+ "disabled": "Išjungta",
"discard": "Atšaukti",
"download": "Parsisiųsti",
"duplicate": "Kopijuoti",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Sekcija \"{name}\" negali būti užkrauta",
"error.section.type.invalid": "Sekcijos tipas \"{type}\" yra neteisingas",
+ "error.site.changeTitle.empty": "Pavadinimas negali būti tuščias",
"error.site.changeTitle.permission":
"Neturite leidimo keisti svetainės pavadinimo",
"error.site.update.permission": "Neturite leidimo atnaujinti svetainės",
@@ -155,6 +157,8 @@
"Vienintelio administratoriaus rolės negalima pakeisti",
"error.user.changeRole.permission":
"Neturite leidimo pakeisti vartotojo \"{name}\" rolės",
+ "error.user.changeRole.toAdmin":
+ "Jūs neturite teisių suteikti administratoriaus rolę",
"error.user.create.permission": "Neturite leidimo sukurti šį vartotoją",
"error.user.delete": "Vartotojo \"{name}\" negalima pašalinti",
"error.user.delete.lastAdmin": "Vienintelio administratoriaus negalima pašalinti",
@@ -219,7 +223,8 @@
"error.validation.time": "Prašome įrašyti korektišką laiką",
"error.validation.url": "Prašome įrašyti teisingą URL",
- "field.files.empty": "Dar nėra failų",
+ "field.required": "Laukas privalomas",
+ "field.files.empty": "Pasirinkti",
"field.pages.empty": "Dar nėra puslapių",
"field.structure.delete.confirm": "Ar tikrai norite pašalinti šią eilutę?",
"field.structure.empty": "Dar nėra įrašų",
@@ -229,7 +234,7 @@
"Ar tikrai norite pašalinti
{filename}?",
"files": "Failai",
- "files.empty": "Dar nėra failų",
+ "files.empty": "Įkelti",
"hour": "Valanda",
"insert": "Įterpti",
@@ -291,6 +296,7 @@
"loading": "Kraunasi",
"lock.unsaved": "Neišsaugoti pakeitimai",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Vartotojo {email} neišsaugoti pakeitimai",
"lock.file.isLocked": "Šį failą dabar redaguoja kitas vartotojas {email}, tad jo negalima pekeisti.",
"lock.page.isLocked": "Šį puslapį dabar redaguoja kitas vartotojas {email}, tad jo negalima pekeisti.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Paskelbti",
"pages.status.unlisted": "Nerodomi",
+ "pagination.page": "Puslapis",
+
"password": "Slaptažodis",
"pixel": "Pikselis",
"prev": "Ankstesnis",
@@ -384,6 +392,9 @@
"save": "Išsaugoti",
"search": "Ieškoti",
+
+ "section.required": "Sekcija privaloma",
+
"select": "Pasirinkti",
"settings": "Nustatymai",
"size": "Dydis",
@@ -418,7 +429,7 @@
"upload.error.default": "Nepavyko įkelti failo",
"upload.error.extension": "Neįmanoma įkelti tokio tipo failo",
"upload.error.formSize": "Įkeltas failas viršija MAX_FILE_SIZE nustatymą, kuris buvo nurodytas formoje",
- "upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
+ "upload.error.iniPostSize": "Įkeliamas failas viršija post_max_size nustatymą iš php.ini",
"upload.error.iniSize": "Įkeltas failas viršija upload_max_filesize nustatymą faile php.ini",
"upload.error.noFile": "Failas nebuvo įkeltas",
"upload.error.noFiles": "Failai nebuvo įkelti",
diff --git a/i18n/translations/nb.json b/i18n/translations/nb.json
index cd547c6c65..246245a596 100644
--- a/i18n/translations/nb.json
+++ b/i18n/translations/nb.json
@@ -23,6 +23,7 @@
"delete": "Slett",
"dimensions": "Dimensjoner",
+ "disabled": "Disabled",
"discard": "Forkast",
"download": "Download",
"duplicate": "Duplicate",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Seksjonen \"{name}\" kunne ikke lastes inn",
"error.section.type.invalid": "Seksjonstypen \"{type}\" er ikke gyldig",
+ "error.site.changeTitle.empty": "Tittelen kan ikke være tom",
"error.site.changeTitle.permission":
"Du har ikke tillatelse til å endre tittel på siden",
"error.site.update.permission": "Du har ikke tillatelse til å oppdatere denne siden",
@@ -155,6 +157,8 @@
"Rollen for den siste administratoren kan ikke endres",
"error.user.changeRole.permission":
"Du har ikke tillatelse til å endre rollen for brukeren \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "Du har ikke tilgang til å opprette denne brukeren",
"error.user.delete": "Denne brukeren kunne ikke bli slettet",
"error.user.delete.lastAdmin": "Siste administrator kan ikke slettes",
@@ -219,6 +223,7 @@
"error.validation.time": "Vennligst angi et gyldig tidspunkt",
"error.validation.url": "Vennligst skriv inn en gyldig URL",
+ "field.required": "The field is required",
"field.files.empty": "Ingen filer har blitt valgt",
"field.pages.empty": "Ingen side har blitt valgt",
"field.structure.delete.confirm": "\u00d8nsker du virkelig \u00e5 slette denne oppf\u00f8ringen?",
@@ -291,6 +296,7 @@
"loading": "Laster inn",
"lock.unsaved": "Unsaved changes",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Unsaved changes by {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Publisert",
"pages.status.unlisted": "Unotert",
+ "pagination.page": "Side",
+
"password": "Passord",
"pixel": "Piksel",
"prev": "Forrige",
@@ -384,6 +392,9 @@
"save": "Lagre",
"search": "Søk",
+
+ "section.required": "The section is required",
+
"select": "Velg",
"settings": "Innstillinger",
"size": "Størrelse",
diff --git a/i18n/translations/nl.json b/i18n/translations/nl.json
index 27bc6d6b05..8af316e34a 100644
--- a/i18n/translations/nl.json
+++ b/i18n/translations/nl.json
@@ -23,21 +23,22 @@
"delete": "Verwijderen",
"dimensions": "Dimensies",
+ "disabled": "Uitgeschakeld",
"discard": "Annuleren",
"download": "Download",
"duplicate": "Dupliceren",
"edit": "Wijzig",
- "dialog.files.empty": "No files to select",
- "dialog.pages.empty": "No pages to select",
- "dialog.users.empty": "No users to select",
+ "dialog.files.empty": "Geen bestanden om te selecteren",
+ "dialog.pages.empty": "Geen pagina's om te selecteren",
+ "dialog.users.empty": "Geen gebruikers om te selecteren",
"email": "E-mailadres",
"email.placeholder": "mail@voorbeeld.nl",
"error.access.login": "Ongeldige login",
"error.access.panel": "Je hebt geen toegang tot het Panel",
- "error.access.view": "You are not allowed to access this part of the panel",
+ "error.access.view": "Je hebt geen toegangsrechten voor deze zone van het Panel",
"error.avatar.create.fail": "De avatar kon niet worden geupload",
"error.avatar.delete.fail": "De avatar kan niet worden verwijderd",
@@ -52,7 +53,7 @@
"error.field.converter.invalid": "Ongeldige converter \"{converter}\"",
- "error.file.changeName.empty": "The name must not be empty",
+ "error.file.changeName.empty": "De naam mag niet leeg zijn",
"error.file.changeName.permission":
"Je hebt geen rechten om de naam te wijzigen van \"{filename}\"",
"error.file.duplicate": "Er bestaat al een bestand met de naam \"{filename}\"",
@@ -73,9 +74,9 @@
"error.form.incomplete": "Verbeter alle fouten in het formulier",
"error.form.notSaved": "Het formulier kon niet worden opgeslagen",
- "error.language.code": "Please enter a valid code for the language",
- "error.language.duplicate": "The language already exists",
- "error.language.name": "Please enter a valid name for the language",
+ "error.language.code": "Vul een geldige code voor deze taal in",
+ "error.language.duplicate": "De taal bestaat al",
+ "error.language.name": "Vul een geldige naam voor deze taal in",
"error.license.format": "Vul een gelidge licentie-key in",
"error.license.email": "Gelieve een geldig emailadres in te voeren",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "De zone \"{name}\" kan niet worden geladen",
"error.section.type.invalid": "Zone-type \"{type}\" is niet geldig",
+ "error.site.changeTitle.empty": "De titel mag niet leeg zijn",
"error.site.changeTitle.permission":
"Je hebt geen rechten om de titel van de site te wijzigen",
"error.site.update.permission": "Je hebt geen rechten om de site te updaten",
@@ -155,6 +157,8 @@
"De rol van de laatste beheerder kan niet worden gewijzigd",
"error.user.changeRole.permission":
"Je hebt geen rechten om de rol van gebruiker \"{name}\" te wijzigen",
+ "error.user.changeRole.toAdmin":
+ "Je hebt geen rechten om de rol van iemand te wijzigen naar admin",
"error.user.create.permission": "Je hebt geen rechten om deze gebruiker aan te maken",
"error.user.delete": "De gebruiker \"{name}\" kan niet worden verwijderd",
"error.user.delete.lastAdmin": "Je kan de laatste admin niet verwijderen",
@@ -184,9 +188,9 @@
"error.validation.contains":
"Vul een waarde in die \"{needle}\" bevat",
"error.validation.date": "Vul een geldige datum in",
- "error.validation.date.after": "Please enter a date after {date}",
- "error.validation.date.before": "Please enter a date before {date}",
- "error.validation.date.between": "Please enter a date between {min} and {max}",
+ "error.validation.date.after": "Vul een datum in na {date}",
+ "error.validation.date.before": "Vul een datum in voor {date}",
+ "error.validation.date.between": "Vul een datum in tussen {min} en {max}",
"error.validation.denied": "Weiger",
"error.validation.different": "De invoer mag niet \"{other}\" zijn",
"error.validation.email": "Gelieve een geldig emailadres in te voeren",
@@ -219,6 +223,7 @@
"error.validation.time": "Vul een geldige tijd in",
"error.validation.url": "Vul een geldige URL in",
+ "field.required": "Dit veld is verplicht",
"field.files.empty": "Nog geen bestanden geselecteerd",
"field.pages.empty": "Nog geen pagina's geselecteerd",
"field.structure.delete.confirm": "Wil je deze entry verwijderen?",
@@ -290,7 +295,8 @@
"loading": "Laden",
- "lock.unsaved": "Unsaved changes",
+ "lock.unsaved": "Niet opgeslagen wijzigingen",
+ "lock.unsaved.empty": "Er zijn geen niet opgeslagen wijzigingen meer",
"lock.isLocked": "Niet opgeslagen wijzigingen door {email}",
"lock.file.isLocked": "Dit bestand wordt momenteel bewerkt door {email} en kan niet worden gewijzigd.",
"lock.page.isLocked": "Deze pagina wordt momenteel bewerkt door {email} en kan niet worden gewijzigd.",
@@ -348,7 +354,7 @@
"page.draft.create": "Maak concept",
"page.duplicate.appendix": "Kopiëren",
"page.duplicate.files": "Kopieer bestanden",
- "page.duplicate.pages": "Copy pages",
+ "page.duplicate.pages": "Kopieer pagina's",
"page.status": "Status",
"page.status.draft": "Concept",
"page.status.draft.description":
@@ -364,6 +370,8 @@
"pages.status.listed": "Gepubliceerd",
"pages.status.unlisted": "Niet gepubliceerd",
+ "pagination.page": "Pagina",
+
"password": "Wachtwoord",
"pixel": "Pixel",
"prev": "Vorige",
@@ -384,6 +392,9 @@
"save": "Opslaan",
"search": "Zoeken",
+
+ "section.required": "De sectie is verplicht",
+
"select": "Selecteren",
"settings": "Opties",
"size": "Grootte",
@@ -413,17 +424,17 @@
"translation.name": "Nederlands",
"upload": "Upload",
- "upload.error.cantMove": "The uploaded file could not be moved",
- "upload.error.cantWrite": "Failed to write file to disk",
- "upload.error.default": "The file could not be uploaded",
- "upload.error.extension": "File upload stopped by extension",
- "upload.error.formSize": "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the form",
- "upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
- "upload.error.iniSize": "The uploaded file exceeds the upload_max_filesize directive in php.ini",
- "upload.error.noFile": "No file was uploaded",
- "upload.error.noFiles": "No files were uploaded",
- "upload.error.partial": "The uploaded file was only partially uploaded",
- "upload.error.tmpDir": "Missing a temporary folder",
+ "upload.error.cantMove": "Het geüploadde bestand kon niet worden verplaatst",
+ "upload.error.cantWrite": "Fout bij het schrijven van het bestand naar de schijf",
+ "upload.error.default": "Het bestand kan niet worden geüpload",
+ "upload.error.extension": "Kan bestand niet uploaden vanwege de extensie",
+ "upload.error.formSize": "Het geüploadde bestand is groter dan de MAX_FILE_SIZE die is aangegeven in het formulier",
+ "upload.error.iniPostSize": "Het geüploadde bestand is groter dan de post_max_size in php.ini",
+ "upload.error.iniSize": "Het geüploadde bestand is groter dan de upload_max_filesize in php.ini",
+ "upload.error.noFile": "Er is geen bestand geüpload",
+ "upload.error.noFiles": "Er zijn geen bestanden geüpload",
+ "upload.error.partial": "Het geüploadde bestand is slechts gedeeltelijk geüpload",
+ "upload.error.tmpDir": "Er mist een tijdelijke map",
"upload.errors": "Foutmelding",
"upload.progress": "Uploaden...",
diff --git a/i18n/translations/pl.json b/i18n/translations/pl.json
index 3d5f0ad35d..16350d0c9f 100644
--- a/i18n/translations/pl.json
+++ b/i18n/translations/pl.json
@@ -23,6 +23,7 @@
"delete": "Usu\u0144",
"dimensions": "Wymiary",
+ "disabled": "Disabled",
"discard": "Odrzu\u0107",
"download": "Pobierz",
"duplicate": "Zduplikuj",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Nie udało się załadować sekcji \"{name}\"",
"error.section.type.invalid": "Typ sekcji \"{type}\" jest nieprawidłowy",
+ "error.site.changeTitle.empty": "Tytuł nie może być pusty",
"error.site.changeTitle.permission":
"Nie masz uprawnień, by zmienić tytuł strony",
"error.site.update.permission": "Nie masz uprawnień, by zaktualizować stronę",
@@ -155,6 +157,8 @@
"Nie można zmienić roli ostatniego administratora",
"error.user.changeRole.permission":
"Nie masz uprawnień, by zmienić rolę użytkownika \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "Nie masz uprawnień, by utworzyć tego użytkownika",
"error.user.delete": "Nie można usunąć użytkownika \"{name}\"",
"error.user.delete.lastAdmin": "Nie można usunąć ostatniego administratora",
@@ -219,6 +223,7 @@
"error.validation.time": "Wprowadź poprawny czas",
"error.validation.url": "Wprowadź poprawny adres URL",
+ "field.required": "The field is required",
"field.files.empty": "Nie wybrano jeszcze żadnych plików",
"field.pages.empty": "Nie wybrano jeszcze żadnych stron",
"field.structure.delete.confirm": "Czy na pewno chcesz usunąć ten wiersz?",
@@ -291,6 +296,7 @@
"loading": "Ładuję",
"lock.unsaved": "Niezapisane zmiany",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Niezapisane zmiany autorstwa {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Opublikowane",
"pages.status.unlisted": "Nie katalogowana",
+ "pagination.page": "Strona",
+
"password": "Has\u0142o",
"pixel": "Piksel",
"prev": "Poprzednie",
@@ -384,6 +392,9 @@
"save": "Zapisz",
"search": "Szukaj",
+
+ "section.required": "The section is required",
+
"select": "Wybierz",
"settings": "Ustawienia",
"size": "Rozmiar",
diff --git a/i18n/translations/pt_BR.json b/i18n/translations/pt_BR.json
index 10adc3f9b6..22a1855432 100644
--- a/i18n/translations/pt_BR.json
+++ b/i18n/translations/pt_BR.json
@@ -23,6 +23,7 @@
"delete": "Excluir",
"dimensions": "Dimensões",
+ "disabled": "Disabled",
"discard": "Descartar",
"download": "Download",
"duplicate": "Duplicate",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "A seção \"{name}\" não pôde ser carregada",
"error.section.type.invalid": "O tipo da seção \"{type}\" não é válido",
+ "error.site.changeTitle.empty": "O título não pode ficar em branco",
"error.site.changeTitle.permission":
"Você não tem permissão para alterar o título do site",
"error.site.update.permission": "Você não tem permissão para atualizar o site",
@@ -155,6 +157,8 @@
"O papel do último administrador não pode ser alterado",
"error.user.changeRole.permission":
"Você não tem permissão para alterar o papel do usuário \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "Você não tem permissão para criar este usuário",
"error.user.delete": "O usuário \"{name}\" não pode ser excluído",
"error.user.delete.lastAdmin": "O último administrador não pode ser excluído",
@@ -219,6 +223,7 @@
"error.validation.time": "Digite uma hora válida",
"error.validation.url": "Digite uma URL válida",
+ "field.required": "The field is required",
"field.files.empty": "Nenhum arquivo selecionado",
"field.pages.empty": "Nenhuma página selecionada",
"field.structure.delete.confirm": "Deseja realmente excluir este registro?",
@@ -291,6 +296,7 @@
"loading": "Carregando",
"lock.unsaved": "Unsaved changes",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Unsaved changes by {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Publicadas",
"pages.status.unlisted": "Não listadas",
+ "pagination.page": "Página",
+
"password": "Senha",
"pixel": "Pixel",
"prev": "Anterior",
@@ -384,6 +392,9 @@
"save": "Salvar",
"search": "Buscar",
+
+ "section.required": "The section is required",
+
"select": "Selecionar",
"settings": "Configurações",
"size": "Tamanho",
diff --git a/i18n/translations/pt_PT.json b/i18n/translations/pt_PT.json
index e4c179aa91..35f633d48d 100644
--- a/i18n/translations/pt_PT.json
+++ b/i18n/translations/pt_PT.json
@@ -23,6 +23,7 @@
"delete": "Excluir",
"dimensions": "Dimensões",
+ "disabled": "Disabled",
"discard": "Descartar",
"download": "Download",
"duplicate": "Duplicate",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "A seção \"{name}\" não pôde ser carregada",
"error.section.type.invalid": "O tipo da seção \"{type}\" não é válido",
+ "error.site.changeTitle.empty": "O título não pode ficar em branco",
"error.site.changeTitle.permission":
"Não tem permissões para alterar o título do site",
"error.site.update.permission": "Não tem permissões para atualizar o site",
@@ -155,6 +157,8 @@
"A função do último administrador não pode ser alterado",
"error.user.changeRole.permission":
"Não tem permissões para alterar a função do utilizador \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "Não tem permissões para criar este utilizador",
"error.user.delete": "O utilizador \"{name}\" não pode ser excluído",
"error.user.delete.lastAdmin": "O último administrador não pode ser excluído",
@@ -219,6 +223,7 @@
"error.validation.time": "Digite uma hora válida",
"error.validation.url": "Digite uma URL válida",
+ "field.required": "The field is required",
"field.files.empty": "Nenhum arquivo selecionado",
"field.pages.empty": "Nenhuma página selecionada",
"field.structure.delete.confirm": "Deseja realmente excluir este registro?",
@@ -291,6 +296,7 @@
"loading": "A carregar",
"lock.unsaved": "Unsaved changes",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Unsaved changes by {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Publicadas",
"pages.status.unlisted": "Não listadas",
+ "pagination.page": "Página",
+
"password": "Palavra-passe",
"pixel": "Pixel",
"prev": "Anterior",
@@ -384,6 +392,9 @@
"save": "Salvar",
"search": "Buscar",
+
+ "section.required": "The section is required",
+
"select": "Selecionar",
"settings": "Configurações",
"size": "Tamanho",
diff --git a/i18n/translations/ru.json b/i18n/translations/ru.json
index 3c5c9f94be..53ec3dd01f 100644
--- a/i18n/translations/ru.json
+++ b/i18n/translations/ru.json
@@ -23,6 +23,7 @@
"delete": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c",
"dimensions": "Размеры",
+ "disabled": "Отключено",
"discard": "\u0421\u0431\u0440\u043e\u0441",
"download": "Скачать",
"duplicate": "Дублировать",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Секция \"{name}\" не может быть загружена",
"error.section.type.invalid": "Тип секции {type} неверный",
+ "error.site.changeTitle.empty": "Название не может быть пустым",
"error.site.changeTitle.permission":
"У вас нет права поменять название сайта",
"error.site.update.permission": "У вас нет права обновить сайт",
@@ -155,6 +157,8 @@
"Роль единственного администратора нельзя поменять",
"error.user.changeRole.permission":
"У вас нет права поменять поль для пользователя \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "У вас нет прав предоставить роль администратора",
"error.user.create.permission": "У вас нет права создать этого пользователя",
"error.user.delete": "\u0410\u043a\u043a\u0430\u0443\u043d\u0442 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d",
"error.user.delete.lastAdmin": "\u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430",
@@ -219,6 +223,7 @@
"error.validation.time": "Пожалуйста, впишите правильную дату",
"error.validation.url": "Пожалуйста, впишите правильный URL",
+ "field.required": "Поле обязательно",
"field.files.empty": "Еще не выбраны файлы",
"field.pages.empty": "Еще не выбраны страницы",
"field.structure.delete.confirm": "Вы точно хотите удалить эту запись?",
@@ -291,6 +296,7 @@
"loading": "Загрузка",
"lock.unsaved": "Несохраненные изменения",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Несохраненные изменения пользователя {email}",
"lock.file.isLocked": "В данный момент этот файл редактирует {email}, поэтому его нельзя изменить.",
"lock.page.isLocked": "В данный момент эту страницу редактирует {email}, поэтому его нельзя изменить.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Опубликовано",
"pages.status.unlisted": "Скрытая",
+ "pagination.page": "Страница",
+
"password": "\u041f\u0430\u0440\u043e\u043b\u044c",
"pixel": "Пиксель",
"prev": "Предыдущий",
@@ -384,6 +392,9 @@
"save": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c",
"search": "Поиск",
+
+ "section.required": "Секция обязательна",
+
"select": "Выбрать",
"settings": "Настройка",
"size": "Размер",
@@ -418,7 +429,7 @@
"upload.error.default": "Не получилось загрузить файл",
"upload.error.extension": "Загрузка файла не удалась из за расширения",
"upload.error.formSize": "Загруженный файл больше чем MAX_FILE_SIZE настройка в форме",
- "upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
+ "upload.error.iniPostSize": "Загружаемый файл больше чем post_max_size настройка в php.ini",
"upload.error.iniSize": "Загруженный файл больше чем upload_max_filesize настройка в php.ini",
"upload.error.noFile": "Файл не был загружен",
"upload.error.noFiles": "Файлы не были загружены",
diff --git a/i18n/translations/sk.json b/i18n/translations/sk.json
index e9908cb7cf..8c8b34f1e3 100644
--- a/i18n/translations/sk.json
+++ b/i18n/translations/sk.json
@@ -23,6 +23,7 @@
"delete": "Zmazať",
"dimensions": "Rozmery",
+ "disabled": "Disabled",
"discard": "Zahodiť",
"download": "Download",
"duplicate": "Duplicate",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Sekciu \"{name}\" sa nepodarilo nahrať",
"error.section.type.invalid": "Typ sekcie \"{type}\" nie je platný",
+ "error.site.changeTitle.empty": "Titulok nemôže byť prázdny",
"error.site.changeTitle.permission":
"Nemáte povolenie na zmenu titulku pre portál",
"error.site.update.permission": "Nemáte povolenie na aktualizovanie portálu",
@@ -155,6 +157,8 @@
"Rolu pre posledného administrátora nie je možné zmeniť",
"error.user.changeRole.permission":
"Nemáte povolenie na zmenu role pre užívateľa \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "You are not allowed to promote someone to the admin role",
"error.user.create.permission": "Nemáte povolenie na vytvorenie tohto užívateľa",
"error.user.delete": "Užívateľa \"{name}\" nie je možné zmazať",
"error.user.delete.lastAdmin": "Posledného administrátora nie je možné zmazať",
@@ -219,6 +223,7 @@
"error.validation.time": "Prosím, zadajte platný čas",
"error.validation.url": "Prosím, zadajte platnú URL",
+ "field.required": "The field is required",
"field.files.empty": "Žiadne súbory zatiaľ neboli zvolené",
"field.pages.empty": "Žiadne stránky zatiaľ neboli zvolené",
"field.structure.delete.confirm": "Ste si istý, že chcete zmazať tento riadok?",
@@ -291,6 +296,7 @@
"loading": "Načítavanie",
"lock.unsaved": "Unsaved changes",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Unsaved changes by {email}",
"lock.file.isLocked": "The file is currently being edited by {email} and cannot be changed.",
"lock.page.isLocked": "The page is currently being edited by {email} and cannot be changed.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Zverejnené",
"pages.status.unlisted": "Skryté",
+ "pagination.page": "Stránka",
+
"password": "Heslo",
"pixel": "Pixel",
"prev": "Predchádzajúci",
@@ -384,6 +392,9 @@
"save": "Uložiť",
"search": "Hľadať",
+
+ "section.required": "The section is required",
+
"select": "Zvoliť",
"settings": "Nastavenia",
"size": "Veľkosť",
diff --git a/i18n/translations/sv_SE.json b/i18n/translations/sv_SE.json
index f857d359cb..ca59f7a87e 100644
--- a/i18n/translations/sv_SE.json
+++ b/i18n/translations/sv_SE.json
@@ -23,6 +23,7 @@
"delete": "Radera",
"dimensions": "Dimensioner",
+ "disabled": "Inaktiverad",
"discard": "Kassera",
"download": "Ladda ner",
"duplicate": "Duplicera",
@@ -37,7 +38,7 @@
"error.access.login": "Ogiltig inloggning",
"error.access.panel": "Du saknar behörighet att nå panelen",
- "error.access.view": "You are not allowed to access this part of the panel",
+ "error.access.view": "Du saknar behörighet att nå denna del av panelen",
"error.avatar.create.fail": "Profilbilden kunde inte laddas upp",
"error.avatar.delete.fail": "Profilbilden kunde inte raderas",
@@ -52,7 +53,7 @@
"error.field.converter.invalid": "Ogiltig omvandlare \"{converter}\"",
- "error.file.changeName.empty": "The name must not be empty",
+ "error.file.changeName.empty": "Namnet får inte vara tomt",
"error.file.changeName.permission":
"Du har inte behörighet att ändra namnet på \"{filename}\"",
"error.file.duplicate": "En fil med namnet \"{filename}\" existerar redan",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "Sektionen \"{name}\" kunde inte laddas",
"error.section.type.invalid": "Sektionstypen \"{type}\" är inte giltig",
+ "error.site.changeTitle.empty": "Titeln får inte vara tom",
"error.site.changeTitle.permission":
"Du har inte behörighet att ändra titeln på webbplatsen",
"error.site.update.permission": "Du har inte behörighet att uppdatera webbplatsen",
@@ -155,6 +157,8 @@
"Rollen för den återstående adminanvändaren kan inte ändras",
"error.user.changeRole.permission":
"Du har inte behörighet att ändra rollen för användaren \"{name}\"",
+ "error.user.changeRole.toAdmin":
+ "Du har inte behörighet att ge någon en administratörsroll",
"error.user.create.permission": "Du har inte behörighet att skapa denna användare",
"error.user.delete": "Användaren kan inte raderas",
"error.user.delete.lastAdmin": "Den återstående administratören kan inte raderas",
@@ -219,6 +223,7 @@
"error.validation.time": "Ange en giltig tid",
"error.validation.url": "Ange en giltig URL",
+ "field.required": "Fältet krävs",
"field.files.empty": "Inga filer valda än",
"field.pages.empty": "Inga sidor valda än",
"field.structure.delete.confirm": "Vill du verkligen radera denna rad?",
@@ -291,6 +296,7 @@
"loading": "Laddar",
"lock.unsaved": "Osparade ändringar",
+ "lock.unsaved.empty": "There are no more unsaved changes",
"lock.isLocked": "Osparade ändringar av {email}",
"lock.file.isLocked": "Filen redigeras just nu av {email} och kan inte redigeras.",
"lock.page.isLocked": "Sidan redigeras just nu av {email} och kan inte redigeras.",
@@ -364,6 +370,8 @@
"pages.status.listed": "Publicerade",
"pages.status.unlisted": "Olistade",
+ "pagination.page": "Sida",
+
"password": "L\u00f6senord",
"pixel": "Pixel",
"prev": "Föregående",
@@ -384,6 +392,9 @@
"save": "Spara",
"search": "Sök",
+
+ "section.required": "Sektionen krävs",
+
"select": "Välj",
"settings": "Inställningar",
"size": "Storlek",
@@ -413,17 +424,17 @@
"translation.name": "Svenska",
"upload": "Ladda upp",
- "upload.error.cantMove": "The uploaded file could not be moved",
- "upload.error.cantWrite": "Failed to write file to disk",
- "upload.error.default": "The file could not be uploaded",
- "upload.error.extension": "File upload stopped by extension",
- "upload.error.formSize": "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the form",
- "upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
- "upload.error.iniSize": "The uploaded file exceeds the upload_max_filesize directive in php.ini",
- "upload.error.noFile": "No file was uploaded",
- "upload.error.noFiles": "No files were uploaded",
- "upload.error.partial": "The uploaded file was only partially uploaded",
- "upload.error.tmpDir": "Missing a temporary folder",
+ "upload.error.cantMove": "Den överförda filen kunde inte flyttas",
+ "upload.error.cantWrite": "Det gick inte att skriva filen till hårddisken",
+ "upload.error.default": "Filen kunde inte laddas upp",
+ "upload.error.extension": "Filuppladdningen förhindrades på grund av filändelsen",
+ "upload.error.formSize": "Den överförda filen överskrider den maximala filstorlek som anges i formuläret (MAX_FILE_SIZE)",
+ "upload.error.iniPostSize": "Den överförda filen överskrider post_max_size-direktivet i php.ini",
+ "upload.error.iniSize": "Den överförda filen överskrider direktivet upload_max_filesize i php.ini",
+ "upload.error.noFile": "Ingen fil laddades upp",
+ "upload.error.noFiles": "Inga filer laddades upp",
+ "upload.error.partial": "Den överförda filen laddades bara delvis upp",
+ "upload.error.tmpDir": "Saknar en temporär mapp",
"upload.errors": "Fel",
"upload.progress": "Laddar upp...",
diff --git a/i18n/translations/tr.json b/i18n/translations/tr.json
index 163bda3ce1..f8f76b2dba 100644
--- a/i18n/translations/tr.json
+++ b/i18n/translations/tr.json
@@ -23,6 +23,7 @@
"delete": "Sil",
"dimensions": "Boyutlar",
+ "disabled": "Devredışı",
"discard": "Vazge\u00e7",
"download": "İndir",
"duplicate": "Kopyala",
@@ -137,6 +138,7 @@
"error.section.notLoaded": "\"{name}\" bölümü yüklenemedi",
"error.section.type.invalid": "\"{type}\" tipi geçerli değil",
+ "error.site.changeTitle.empty": "Başlık boş bırakılamaz",
"error.site.changeTitle.permission":
"Sitenin başlığını değiştiremezsin",
"error.site.update.permission": "Siteyi güncellemenize izin verilmiyor",
@@ -155,6 +157,8 @@
"Son yöneticinin rolü değiştirilemez",
"error.user.changeRole.permission":
"\"{name}\" kullanıcısının rolünü değiştiremezsin",
+ "error.user.changeRole.toAdmin":
+ "Birini yönetici rolüne tanıtmanıza izin verilmiyor",
"error.user.create.permission": "Bu kullanıcıyı oluşturmanıza izin verilmiyor",
"error.user.delete": "\"{name}\" kullanıcısı silinemedi",
"error.user.delete.lastAdmin": "Son y\u00f6netici kullan\u0131c\u0131y\u0131 silemezsiniz",
@@ -219,6 +223,7 @@
"error.validation.time": "Lütfen geçerli bir zaman girin",
"error.validation.url": "Lütfen geçerli bir adres girin",
+ "field.required": "Alan gereklidir",
"field.files.empty": "Henüz dosya seçilmedi",
"field.pages.empty": "Henüz sayfa seçilmedi",
"field.structure.delete.confirm": "Bu girdiyi silmek istedi\u011finizden emin misiniz?",
@@ -291,6 +296,7 @@
"loading": "Yükleniyor",
"lock.unsaved": "Kaydedilmemiş değişiklikler",
+ "lock.unsaved.empty": "Daha fazla kaydedilmemiş değişiklik yok",
"lock.isLocked": "{email} tarafından kaydedilmemiş değişiklikler",
"lock.file.isLocked": "Dosya şu anda {email} tarafından düzenlenmektedir ve değiştirilemez.",
"lock.page.isLocked": "Sayfa şu anda {email} tarafından düzenlenmektedir ve değiştirilemez.",
@@ -346,7 +352,7 @@
"Bu sayfada alt sayfalar var.
Tüm alt sayfalar da silinecek.",
"page.delete.confirm.title": "Onaylamak için sayfa başlığını girin",
"page.draft.create": "Taslak oluştur",
- "page.duplicate.appendix": "Kopyala",
+ "page.duplicate.appendix": "Kopya",
"page.duplicate.files": "Dosyaları kopyala",
"page.duplicate.pages": "Sayfaları kopyala",
"page.status": "Durum",
@@ -364,6 +370,8 @@
"pages.status.listed": "Yayınlandı",
"pages.status.unlisted": "Liste Dışı",
+ "pagination.page": "Sayfa",
+
"password": "\u015eifre",
"pixel": "Piksel",
"prev": "Önceki",
@@ -384,6 +392,9 @@
"save": "Kaydet",
"search": "Arama",
+
+ "section.required": "Bölüm gereklidir",
+
"select": "Seç",
"settings": "Ayarlar",
"size": "Boyut",
@@ -418,7 +429,7 @@
"upload.error.default": "Dosya yüklenemedi",
"upload.error.extension": "Dosya yükleme uzantısı tarafından durduruldu",
"upload.error.formSize": "Yüklenen dosya, formda belirtilen MAX_FILE_SIZE yönergesini aşıyor",
- "upload.error.iniPostSize": "The uploaded file exceeds the post_max_size directive in php.ini",
+ "upload.error.iniPostSize": "Yüklenen dosya php.ini içindeki post_max_size yönergesini aşıyor",
"upload.error.iniSize": "Yüklenen dosya php.ini içindeki upload_max_filesize yönergesini aşıyor",
"upload.error.noFile": "Dosya yüklenmedi",
"upload.error.noFiles": "Dosyalar yüklenmedi",
diff --git a/panel/dist/css/app.css b/panel/dist/css/app.css
index f249e71c1b..d25333458c 100644
--- a/panel/dist/css/app.css
+++ b/panel/dist/css/app.css
@@ -1 +1 @@
-*,:after,:before{margin:0;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}noscript{padding:1.5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;height:100vh;text-align:center}html{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;background:#efefef}body,html{color:#16171a;overflow:hidden;height:100%}a{color:inherit;text-decoration:none}li{list-style:none}b,strong{font-weight:600}.fade-enter-active,.fade-leave-active{-webkit-transition:opacity .5s;transition:opacity .5s}.fade-enter,.fade-leave-to{opacity:0}.k-panel{position:absolute;top:0;right:0;bottom:0;left:0;background:#efefef}.k-panel[data-loading]{-webkit-animation:LoadingCursor .5s;animation:LoadingCursor .5s}.k-panel-header{position:absolute;top:0;left:0;right:0;z-index:300}.k-panel .k-form-buttons{position:fixed;bottom:0;left:0;right:0;z-index:300}.k-panel-view{position:absolute;top:0;right:0;bottom:0;left:0;padding-bottom:6rem;overflow-y:scroll;-webkit-overflow-scrolling:touch;-webkit-transform:translateZ(0);transform:translateZ(0)}.k-panel[data-dialog] .k-panel-view{overflow:hidden;-webkit-transform:none;transform:none}.k-panel[data-topbar] .k-panel-view{top:2.5rem}.k-panel[data-dragging],.k-panel[data-loading]:after{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.k-offline-warning{position:fixed;content:" ";top:0;right:0;bottom:0;left:0;z-index:900;background:rgba(22,23,26,.7);content:"offline";display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;color:#fff}@-webkit-keyframes LoadingCursor{to{cursor:progress}}@keyframes LoadingCursor{to{cursor:progress}}@-webkit-keyframes Spin{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes Spin{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.k-offscreen{-webkit-clip-path:inset(100%);clip-path:inset(100%);clip:rect(1px,1px,1px,1px);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}.k-icons{position:absolute;width:0;height:0}.k-dialog{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:fixed;top:0;right:0;bottom:0;left:0;border:0;width:100%;height:100%;background:rgba(22,23,26,.6);z-index:600;-webkit-transform:translateZ(0);transform:translateZ(0)}.k-dialog,.k-dialog-box{display:-webkit-box;display:-ms-flexbox;display:flex}.k-dialog-box{position:relative;background:#efefef;width:22rem;-webkit-box-shadow:rgba(22,23,26,.2) 0 2px 10px;box-shadow:0 2px 10px rgba(22,23,26,.2);border-radius:1px;line-height:1;max-height:calc(100vh - 3rem);margin:1.5rem;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.k-dialog-box[data-size=small]{width:20rem}.k-dialog-box[data-size=medium]{width:30rem}.k-dialog-box[data-size=large]{width:40rem}.k-dialog-notification{padding:.75rem 1.5rem;background:#16171a;width:100%;line-height:1.25rem;color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-dialog-notification[data-theme=error]{background:#d16464;color:#000}.k-dialog-notification[data-theme=success]{background:#a7bd68;color:#000}.k-dialog-notification p{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;word-wrap:break-word;overflow:hidden}.k-dialog-notification .k-button{display:-webkit-box;display:-ms-flexbox;display:flex;margin-left:1rem}.k-dialog-body{padding:1.5rem;overflow-y:auto;overflow-x:hidden}.k-dialog-body .k-fieldset{padding-bottom:.5rem}.k-dialog-footer{border-top:1px solid #ccc;padding:0;border-bottom-left-radius:1px;border-bottom-right-radius:1px;line-height:1;-ms-flex-negative:0;flex-shrink:0}.k-dialog-footer .k-button-group{display:-webkit-box;display:-ms-flexbox;display:flex;margin:0;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.k-dialog-footer .k-button-group .k-button{padding:.75rem 1rem;line-height:1.25rem}.k-dialog-footer .k-button-group .k-button:first-child{text-align:left;padding-left:1.5rem}.k-dialog-footer .k-button-group .k-button:last-child{text-align:right;padding-right:1.5rem}.k-error-details{background:#fff;display:block;overflow:auto;padding:1rem;font-size:.875rem;line-height:1.25em;margin-top:.75rem}.k-error-details dt{color:#d16464;margin-bottom:.25rem}.k-error-details dd{overflow:hidden;overflow-wrap:break-word;text-overflow:ellipsis}.k-error-details dd:not(:last-of-type){margin-bottom:1.5em}.k-error-details li:not(:last-child){border-bottom:1px solid #efefef;padding-bottom:.25rem;margin-bottom:.25rem}.k-files-dialog .k-list-item{cursor:pointer}.k-page-remove-warning{margin:1.5rem 0}.k-page-remove-warning .k-box{font-size:1rem;line-height:1.5em;padding-top:.75rem;padding-bottom:.75rem}.k-pages-dialog-navbar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-bottom:.5rem;padding-right:38px}.k-pages-dialog-navbar .k-button{width:38px}.k-pages-dialog-navbar .k-button[disabled]{opacity:0}.k-pages-dialog-navbar .k-headline{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.k-pages-dialog-search{margin-bottom:.5rem}.k-pages-dialog .k-list-item{cursor:pointer}.k-pages-dialog .k-list-item .k-button[data-theme=disabled],.k-pages-dialog .k-list-item .k-button[disabled]{opacity:.25}.k-pages-dialog .k-list-item .k-button[data-theme=disabled]:hover{opacity:1}.k-users-dialog .k-list-item{cursor:pointer}.k-calendar-input{padding:.5rem;background:#16171a;color:#efefef;border-radius:1px}.k-calendar-table{table-layout:fixed;width:100%;min-width:15rem;padding-top:.5rem}.k-calendar-input>nav{display:-webkit-box;display:-ms-flexbox;display:flex;direction:ltr}.k-calendar-input>nav .k-button{padding:.5rem}.k-calendar-selects{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}[dir=ltr] .k-calendar-selects{direction:ltr}[dir=rtl] .k-calendar-selects{direction:rtl}.k-calendar-selects .k-select-input{padding:0 .5rem;font-weight:400;font-size:.875rem}.k-calendar-selects .k-select-input:focus-within{color:#81a2be!important}.k-calendar-input th{padding:.5rem 0;color:#999;font-size:.75rem;font-weight:400;text-align:center}.k-calendar-day .k-button{width:2rem;height:2rem;margin:0 auto;color:#fff;line-height:1.75rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:50%;border:2px solid transparent}.k-calendar-day .k-button .k-button-text{opacity:1}.k-calendar-table .k-button:hover{color:#fff}.k-calendar-day:hover .k-button{border-color:hsla(0,0%,100%,.25)}.k-calendar-day[aria-current=date] .k-button{color:#81a2be;font-weight:500}.k-calendar-day[aria-selected=date] .k-button{border-color:#a7bd68;color:#a7bd68}.k-calendar-today{text-align:center;padding-top:.5rem}.k-calendar-today .k-button{color:#81a2be;font-size:.75rem;padding:1rem}.k-calendar-today .k-button-text{opacity:1}.k-counter{font-size:.75rem;color:#16171a;font-weight:600}.k-counter[data-invalid]{color:#c82829}.k-counter-rules{color:#777;font-weight:400}[dir=ltr] .k-counter-rules{padding-left:.5rem}[dir=rtl] .k-counter-rules{padding-right:.5rem}.k-form-submitter{display:none}.k-form-buttons[data-theme=changes]{background:#de935f}.k-form-buttons[data-theme=lock]{background:#d16464}.k-form-buttons[data-theme=unlock]{background:#81a2be}.k-form-buttons .k-view{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.k-form-button,.k-form-buttons .k-view{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-form-button{font-weight:500;white-space:nowrap;line-height:1;height:2.5rem;padding:0 1rem}.k-form-button:first-child{margin-left:-1rem}.k-form-button:last-child{margin-right:-1rem}.k-form-lock-info{display:-webkit-box;display:-ms-flexbox;display:flex;font-size:.875rem;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:1.5em;padding:.625rem 0;margin-right:3rem}.k-form-lock-info>.k-icon{margin-right:.5rem}.k-form-lock-buttons{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0}.k-form-indicator-icon{color:#de935f}.k-form-indicator-info{font-size:.875rem;font-weight:600;padding:.75rem 1rem .25rem;line-height:1.25em;width:15rem}.k-field-label{font-weight:600;display:block;padding:0 0 .75rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;line-height:1.25rem}.k-field-label abbr{text-decoration:none;color:#999;padding-left:.25rem}.k-field-header{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline}.k-field-options{position:absolute;top:calc(-.5rem - 1px)}[dir=ltr] .k-field-options{right:0}[dir=rtl] .k-field-options{left:0}.k-field-options.k-button-group .k-dropdown{height:auto}.k-field-options.k-button-group .k-field-options-button.k-button{padding:.75rem;display:-webkit-box;display:-ms-flexbox;display:flex}.k-field[data-disabled]{cursor:not-allowed}.k-field[data-disabled] :not(.k-text[data-theme=help]){pointer-events:none}.k-field:focus-within>.k-field-header>.k-field-counter{display:block}.k-field-help{padding-top:.5rem}.k-fieldset{border:0}.k-fieldset .k-grid{grid-row-gap:2.25rem}@media screen and (min-width:30em){.k-fieldset .k-grid{grid-column-gap:1.5rem}}.k-sections>.k-column[data-width="1/3"] .k-fieldset .k-grid,.k-sections>.k-column[data-width="1/4"] .k-fieldset .k-grid{grid-template-columns:repeat(1,1fr)}.k-sections>.k-column[data-width="1/3"] .k-fieldset .k-grid .k-column,.k-sections>.k-column[data-width="1/4"] .k-fieldset .k-grid .k-column{grid-column-start:auto}.k-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:1;border:0;outline:0;background:none}.k-input-element{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.k-input-icon{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:0}.k-input[data-disabled]{pointer-events:none}.k-input[data-theme=field]{line-height:1;border:1px solid #ccc;background:#fff}.k-input[data-theme=field]:focus-within{border:1px solid #4271ae;-webkit-box-shadow:rgba(66,113,174,.25) 0 0 0 2px;box-shadow:0 0 0 2px rgba(66,113,174,.25)}.k-input[data-theme=field][data-disabled]{background:#efefef}.k-input[data-theme=field][data-invalid]{border:1px solid rgba(200,40,41,.25);-webkit-box-shadow:rgba(200,40,41,.25) 0 0 3px 2px;box-shadow:0 0 3px 2px rgba(200,40,41,.25)}.k-input[data-theme=field][data-invalid]:focus-within{border:1px solid #c82829;-webkit-box-shadow:rgba(200,40,41,.25) 0 0 0 2px;box-shadow:0 0 0 2px rgba(200,40,41,.25)}.k-input[data-theme=field] .k-input-icon{width:2.25rem}.k-input[data-theme=field] .k-input-after,.k-input[data-theme=field] .k-input-before,.k-input[data-theme=field] .k-input-icon{-ms-flex-item-align:stretch;align-self:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-negative:0;flex-shrink:0}.k-input[data-theme=field] .k-input-after,.k-input[data-theme=field] .k-input-before{padding:0 .5rem}.k-input[data-theme=field] .k-input-before{color:#777;padding-right:0}.k-input[data-theme=field] .k-input-after{color:#777;padding-left:0}.k-input[data-theme=field] .k-input-icon>.k-dropdown{width:100%;height:100%}.k-input[data-theme=field] .k-input-icon-button{width:100%;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-ms-flex-negative:0;flex-shrink:0}.k-input[data-theme=field] .k-number-input,.k-input[data-theme=field] .k-select-input,.k-input[data-theme=field] .k-text-input{padding:.5rem;line-height:1.25rem}.k-input[data-theme=field] .k-date-input .k-select-input,.k-input[data-theme=field] .k-time-input .k-select-input{padding-left:0;padding-right:0}[dir=ltr] .k-input[data-theme=field] .k-date-input .k-select-input:first-child,[dir=ltr] .k-input[data-theme=field] .k-time-input .k-select-input:first-child{padding-left:.5rem}[dir=rtl] .k-input[data-theme=field] .k-date-input .k-select-input:first-child,[dir=rtl] .k-input[data-theme=field] .k-time-input .k-select-input:first-child{padding-right:.5rem}.k-input[data-theme=field] .k-date-input .k-select-input:focus-within,.k-input[data-theme=field] .k-time-input .k-select-input:focus-within{color:#4271ae;font-weight:600}.k-input[data-theme=field] .k-time-input .k-time-input-meridiem{padding-left:.5rem}.k-input[data-theme=field][data-type=checkboxes] .k-checkboxes-input li,.k-input[data-theme=field][data-type=checkboxes] .k-radio-input li,.k-input[data-theme=field][data-type=radio] .k-checkboxes-input li,.k-input[data-theme=field][data-type=radio] .k-radio-input li{min-width:0;overflow-wrap:break-word}.k-input[data-theme=field][data-type=checkboxes] .k-input-before{border-right:1px solid #efefef}.k-input[data-theme=field][data-type=checkboxes] .k-input-element+.k-input-after,.k-input[data-theme=field][data-type=checkboxes] .k-input-element+.k-input-icon{border-left:1px solid #efefef}.k-input[data-theme=field][data-type=checkboxes] .k-input-element{overflow:hidden}.k-input[data-theme=field][data-type=checkboxes] .k-checkboxes-input{display:grid;grid-template-columns:1fr;margin-bottom:-1px;margin-right:-1px}@media screen and (min-width:65em){.k-input[data-theme=field][data-type=checkboxes] .k-checkboxes-input{grid-template-columns:repeat(var(--columns),1fr)}}.k-input[data-theme=field][data-type=checkboxes] .k-checkboxes-input li{border-right:1px solid #efefef;border-bottom:1px solid #efefef}.k-input[data-theme=field][data-type=checkboxes] .k-checkboxes-input label{display:block;line-height:1.25rem;padding:.5rem .5rem}.k-input[data-theme=field][data-type=checkboxes] .k-checkbox-input-icon{top:.625rem;left:.5rem;margin-top:0}.k-input[data-theme=field][data-type=radio] .k-input-before{border-right:1px solid #efefef}.k-input[data-theme=field][data-type=radio] .k-input-element+.k-input-after,.k-input[data-theme=field][data-type=radio] .k-input-element+.k-input-icon{border-left:1px solid #efefef}.k-input[data-theme=field][data-type=radio] .k-input-element{overflow:hidden}.k-input[data-theme=field][data-type=radio] .k-radio-input{display:grid;grid-template-columns:1fr;margin-bottom:-1px;margin-right:-1px}@media screen and (min-width:65em){.k-input[data-theme=field][data-type=radio] .k-radio-input{grid-template-columns:repeat(var(--columns),1fr)}}.k-input[data-theme=field][data-type=radio] .k-radio-input li{border-right:1px solid #efefef;border-bottom:1px solid #efefef}.k-input[data-theme=field][data-type=radio] .k-radio-input label{display:block;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;min-height:2.25rem;line-height:1.25rem;padding:.5rem .5rem}.k-input[data-theme=field][data-type=radio] .k-radio-input label:before{top:.625rem;left:.5rem;margin-top:-1px}.k-input[data-theme=field][data-type=radio] .k-radio-input .k-radio-input-info{display:block;font-size:.875rem;color:#777;line-height:1.25rem;padding-top:.125rem}.k-input[data-theme=field][data-type=radio] .k-radio-input .k-icon{width:2.25rem;height:2.25rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.k-input[data-theme=field][data-type=range] .k-range-input{padding:.5rem}.k-input[data-theme=field][data-type=select]{position:relative}.k-input[data-theme=field][data-type=select] .k-input-icon{position:absolute;top:0;bottom:0}[dir=ltr] .k-input[data-theme=field][data-type=select] .k-input-icon{right:0}[dir=rtl] .k-input[data-theme=field][data-type=select] .k-input-icon{left:0}.k-input[data-theme=field][data-type=tags] .k-tags-input{padding:.25rem .25rem 0 .25rem}.k-input[data-theme=field][data-type=tags] .k-tag{margin-right:.25rem;margin-bottom:.25rem;height:1.75rem;font-size:.875rem}.k-input[data-theme=field][data-type=tags] .k-tags-input input{font-size:.875rem;padding:0 .25rem;height:1.75rem;line-height:1;margin-bottom:.25rem}.k-input[data-theme=field][data-type=tags] .k-tags-input .k-dropdown-content{top:calc(100% + .5rem + 2px)}.k-input[data-theme=field][data-type=multiselect]{position:relative}.k-input[data-theme=field][data-type=multiselect] .k-multiselect-input{padding:.25rem 2rem 0 .25rem;min-height:2.25rem}.k-input[data-theme=field][data-type=multiselect] .k-tag{margin-right:.25rem;margin-bottom:.25rem;height:1.75rem;font-size:.875rem}.k-input[data-theme=field][data-type=multiselect] .k-input-icon{position:absolute;top:0;right:0;bottom:0;pointer-events:none}.k-input[data-theme=field][data-type=textarea] .k-textarea-input-native{padding:.25rem .5rem;line-height:1.5rem}.k-input[data-theme=field][data-type=toggle] .k-input-before{padding-right:.25rem}.k-input[data-theme=field][data-type=toggle] .k-toggle-input{padding-left:.5rem}.k-input[data-theme=field][data-type=toggle] .k-toggle-input-label{padding:0 .5rem 0 .75rem;line-height:2.25rem}.k-upload input{position:absolute;top:0}[dir=ltr] .k-upload input{left:-3000px}[dir=rtl] .k-upload input{right:-3000px}.k-upload .k-headline{margin-bottom:.75rem}.k-upload-error-list,.k-upload-list{line-height:1.5em;font-size:.875rem}.k-upload-list-filename{color:#777}.k-upload-error-list li{padding:.75rem;background:#fff;border-radius:1px}.k-upload-error-list li:not(:last-child){margin-bottom:2px}.k-upload-error-filename{color:#c82829;font-weight:600}.k-upload-error-message{color:#777}.k-checkbox-input{position:relative;cursor:pointer}.k-checkbox-input-native{position:absolute;-webkit-appearance:none;-moz-appearance:none;appearance:none;width:0;height:0;opacity:0}.k-checkbox-input-label{display:block;padding-left:1.75rem}.k-checkbox-input-icon{position:absolute;left:0;width:1rem;height:1rem;border:2px solid #999}.k-checkbox-input-icon svg{position:absolute;width:12px;height:12px;display:none}.k-checkbox-input-icon path{stroke:#fff}.k-checkbox-input-native:checked+.k-checkbox-input-icon{border-color:#16171a;background:#16171a}.k-checkbox-input-native:checked+.k-checkbox-input-icon svg{display:block}.k-checkbox-input-native:focus+.k-checkbox-input-icon{border-color:#4271ae}.k-checkbox-input-native:focus:checked+.k-checkbox-input-icon{background:#4271ae}.k-date-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-date-input-separator{padding:0 .125rem}.k-datetime-input{display:-webkit-box;display:-ms-flexbox;display:flex}.k-datetime-input .k-time-input{padding-left:.5rem}.k-text-input{width:100%;border:0;background:none;font:inherit;color:inherit}.k-text-input::-webkit-input-placeholder{color:#999}.k-text-input::-moz-placeholder{color:#999}.k-text-input:-ms-input-placeholder{color:#999}.k-text-input::-ms-input-placeholder{color:#999}.k-text-input::placeholder{color:#999}.k-text-input:focus{outline:0}.k-text-input:invalid{-webkit-box-shadow:none;box-shadow:none;outline:0}.k-multiselect-input{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;position:relative;font-size:.875rem;min-height:2.25rem;line-height:1}.k-multiselect-input .k-sortable-ghost{background:#4271ae}.k-multiselect-input .k-dropdown-content{width:100%}.k-multiselect-search{margin-top:0!important;color:#fff;background:#16171a;border-bottom:1px dashed hsla(0,0%,100%,.2)}.k-multiselect-search>.k-button-text{-webkit-box-flex:1;-ms-flex:1;flex:1}.k-multiselect-search input{width:100%;color:#fff;background:none;border:none;outline:none;padding:.25rem 0;font:inherit}.k-multiselect-options{position:relative;max-height:240px;overflow-y:scroll;padding:.5rem 0}.k-multiselect-option{position:relative}.k-multiselect-option.selected{color:#a7bd68}.k-multiselect-option.disabled:not(.selected) .k-icon{opacity:0}.k-multiselect-option b{color:#81a2be;font-weight:700}.k-multiselect-value{color:#999;margin-left:.25rem}.k-multiselect-value:before{content:" ("}.k-multiselect-value:after{content:")"}.k-multiselect-input[data-layout=list] .k-tag{width:100%;margin-right:0!important}.k-number-input{width:100%;border:0;background:none;font:inherit;color:inherit}.k-number-input::-webkit-input-placeholder{color:$color-light-grey}.k-number-input::-moz-placeholder{color:$color-light-grey}.k-number-input:-ms-input-placeholder{color:$color-light-grey}.k-number-input::-ms-input-placeholder{color:$color-light-grey}.k-number-input::placeholder{color:$color-light-grey}.k-number-input:focus{outline:0}.k-number-input:invalid{-webkit-box-shadow:none;box-shadow:none;outline:0}.k-radio-input li{position:relative;line-height:1.5rem;padding-left:1.75rem}.k-radio-input input{position:absolute;width:0;height:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;opacity:0}.k-radio-input label{cursor:pointer;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-radio-input label:before{position:absolute;top:.175em;left:0;content:"";width:1rem;height:1rem;border-radius:50%;border:2px solid #999;-webkit-box-shadow:#fff 0 0 0 2px inset;box-shadow:inset 0 0 0 2px #fff}.k-radio-input input:checked+label:before{border-color:#16171a;background:#16171a}.k-radio-input input:focus+label:before{border-color:#4271ae}.k-radio-input input:focus:checked+label:before{background:#4271ae}.k-radio-input-text{display:block}.k-range-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-range-input-native{--min:0;--max:100;--value:0;--range:calc(var(--max) - var(--min));--ratio:calc((var(--value) - var(--min))/var(--range));--position:calc(8px + var(--ratio)*(100% - 16px));-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:16px;background:transparent;font-size:.875rem;line-height:1}.k-range-input-native::-webkit-slider-thumb{-webkit-appearance:none;appearance:none}.k-range-input-native::-webkit-slider-runnable-track{border:none;border-radius:4px;width:100%;height:4px;background:#ccc;background:-webkit-gradient(linear,left top,left bottom,from(#16171a),to(#16171a)) 0/var(--position) 100% no-repeat #ccc;background:linear-gradient(#16171a,#16171a) 0/var(--position) 100% no-repeat #ccc}.k-range-input-native::-moz-range-track{border:none;border-radius:4px;width:100%;height:4px;background:#ccc}.k-range-input-native::-ms-track{border:none;border-radius:4px;width:100%;height:4px;background:#ccc}.k-range-input-native::-moz-range-progress{height:4px;background:#16171a}.k-range-input-native::-ms-fill-lower{height:4px;background:#16171a}.k-range-input-native::-webkit-slider-thumb{margin-top:-6px;-webkit-box-sizing:border-box;box-sizing:border-box;width:16px;height:16px;background:#efefef;border:4px solid #16171a;border-radius:50%;cursor:pointer}.k-range-input-native::-moz-range-thumb{box-sizing:border-box;width:16px;height:16px;background:#efefef;border:4px solid #16171a;border-radius:50%;cursor:pointer}.k-range-input-native::-ms-thumb{margin-top:0;box-sizing:border-box;width:16px;height:16px;background:#efefef;border:4px solid #16171a;border-radius:50%;cursor:pointer}.k-range-input-native::-ms-tooltip{display:none}.k-range-input-native:focus{outline:none}.k-range-input-native:focus::-webkit-slider-runnable-track{border:none;border-radius:4px;width:100%;height:4px;background:#ccc;background:-webkit-gradient(linear,left top,left bottom,from(#4271ae),to(#4271ae)) 0/var(--position) 100% no-repeat #ccc;background:linear-gradient(#4271ae,#4271ae) 0/var(--position) 100% no-repeat #ccc}.k-range-input-native:focus::-moz-range-progress{height:4px;background:#4271ae}.k-range-input-native:focus::-ms-fill-lower{height:4px;background:#4271ae}.k-range-input-native:focus::-webkit-slider-thumb{background:#efefef;border:4px solid #4271ae}.k-range-input-native:focus::-moz-range-thumb{background:#efefef;border:4px solid #4271ae}.k-range-input-native:focus::-ms-thumb{background:#efefef;border:4px solid #4271ae}.k-range-input-tooltip{position:relative;max-width:20%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#fff;font-size:.75rem;line-height:1;text-align:center;border-radius:1px;background:#16171a;margin-left:1rem;padding:0 .25rem;white-space:nowrap}.k-range-input-tooltip:after{position:absolute;top:50%;left:-5px;width:0;height:0;-webkit-transform:translateY(-50%);transform:translateY(-50%);border-top:5px solid transparent;border-right:5px solid #16171a;border-bottom:5px solid transparent;content:""}.k-range-input-tooltip>*{padding:4px}.k-select-input{position:relative;display:block;cursor:pointer;overflow:hidden}.k-select-input-native{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;width:100%;font:inherit;z-index:1;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}.k-select-input-native[disabled]{cursor:default}.k-select-input-native{font-weight:400}.k-tags-input{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.k-tags-input .k-sortable-ghost{background:#4271ae}.k-tags-input-element{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;min-width:0}.k-tags-input:focus-within .k-tags-input-element{-ms-flex-preferred-size:4rem;flex-basis:4rem}.k-tags-input-element input{font:inherit;border:0;width:100%;background:none}.k-tags-input-element input:focus{outline:0}.k-tags-input[data-layout=list] .k-tag{width:100%;margin-right:0!important}.k-textarea-input-wrapper{position:relative}.k-textarea-input-native{resize:none;border:0;width:100%;background:none;font:inherit;line-height:1.5em;color:inherit}.k-textarea-input-native::-webkit-input-placeholder{color:#999}.k-textarea-input-native::-moz-placeholder{color:#999}.k-textarea-input-native:-ms-input-placeholder{color:#999}.k-textarea-input-native::-ms-input-placeholder{color:#999}.k-textarea-input-native::placeholder{color:#999}.k-textarea-input-native:focus{outline:0}.k-textarea-input-native:invalid{-webkit-box-shadow:none;box-shadow:none;outline:0}.k-textarea-input-native[data-size=small]{min-height:7.5rem}.k-textarea-input-native[data-size=medium]{min-height:15rem}.k-textarea-input-native[data-size=large]{min-height:30rem}.k-textarea-input-native[data-size=huge]{min-height:45rem}.k-textarea-input-native[data-font=monospace]{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}.k-toolbar{margin-bottom:.25rem;color:#aaa}.k-textarea-input:focus-within .k-toolbar{position:-webkit-sticky;position:sticky;top:0;right:0;left:0;z-index:1;-webkit-box-shadow:rgba(0,0,0,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(0,0,0,.05);border-bottom:1px solid rgba(0,0,0,.1);color:#000}.k-time-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:1}.k-time-input-separator{padding:0 .125rem}.k-time-input-meridiem{padding-left:.5rem}.k-toggle-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-toggle-input-native{position:relative;height:16px;width:32px;border-radius:16px;border:2px solid #999;-webkit-box-shadow:inset 0 0 0 2px #fff,inset -16px 0 0 2px #fff;box-shadow:inset 0 0 0 2px #fff,inset -16px 0 0 2px #fff;background-color:#999;outline:0;-webkit-transition:all .1s ease-in-out;transition:all .1s ease-in-out;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;-ms-flex-negative:0;flex-shrink:0}.k-toggle-input-native:checked{border-color:#16171a;-webkit-box-shadow:inset 0 0 0 2px #fff,inset 16px 0 0 2px #fff;box-shadow:inset 0 0 0 2px #fff,inset 16px 0 0 2px #fff;background-color:#16171a}.k-toggle-input-native[disabled]{border-color:#ccc;-webkit-box-shadow:inset 0 0 0 2px #efefef,inset -16px 0 0 2px #efefef;box-shadow:inset 0 0 0 2px #efefef,inset -16px 0 0 2px #efefef;background-color:#ccc}.k-toggle-input-native[disabled]:checked{-webkit-box-shadow:inset 0 0 0 2px #efefef,inset 16px 0 0 2px #efefef;box-shadow:inset 0 0 0 2px #efefef,inset 16px 0 0 2px #efefef}.k-toggle-input-native:focus:checked{border:2px solid #4271ae;background-color:#4271ae}.k-toggle-input-native::-ms-check{opacity:0}.k-toggle-input-label{cursor:pointer;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.k-files-field[data-disabled] *{pointer-events:all!important}body{counter-reset:headline-counter}.k-headline-field{position:relative;padding-top:1.5rem}.k-headline-field[data-numbered]:before{counter-increment:headline-counter;content:counter(headline-counter,decimal-leading-zero);color:#4271ae;font-weight:400;padding-right:.25rem}.k-fieldset>.k-grid .k-column:first-child .k-headline-field{padding-top:0}.k-info-field .k-headline{padding-bottom:.75rem;line-height:1.25rem}.k-line-field{position:relative;border:0;height:3rem;width:auto}.k-line-field:after{position:absolute;content:"";top:50%;margin-top:-1px;left:0;right:0;height:1px;background:#ccc}.k-pages-field[data-disabled] *{pointer-events:all!important}.k-structure-table{table-layout:fixed;width:100%;background:#fff;font-size:.875rem;border-spacing:0;-webkit-box-shadow:rgba(22,23,26,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(22,23,26,.05)}.k-structure-table td,.k-structure-table th{border-bottom:1px solid #efefef;line-height:1.25em;overflow:hidden;text-overflow:ellipsis}[dir=ltr] .k-structure-table td,[dir=ltr] .k-structure-table th{border-right:1px solid #efefef}[dir=rtl] .k-structure-table td,[dir=rtl] .k-structure-table th{border-left:1px solid #efefef}.k-structure-table th{font-weight:400;color:#777;padding:0 .75rem;height:38px}[dir=ltr] .k-structure-table th{text-align:left}[dir=rtl] .k-structure-table th{text-align:right}.k-structure-table td:last-child,.k-structure-table th:last-child{width:38px}[dir=ltr] .k-structure-table td:last-child,[dir=ltr] .k-structure-table th:last-child{border-right:0}[dir=rtl] .k-structure-table td:last-child,[dir=rtl] .k-structure-table th:last-child{border-left:0}.k-structure-table tr:last-child td{border-bottom:0}.k-structure-table tbody tr:hover td{background:hsla(0,0%,93.7%,.25)}@media screen and (max-width:65em){.k-structure-table td,.k-structure-table th{display:none}.k-structure-table td:first-child,.k-structure-table td:last-child,.k-structure-table td:nth-child(2),.k-structure-table th:first-child,.k-structure-table th:last-child,.k-structure-table th:nth-child(2){display:table-cell}}.k-structure-table .k-structure-table-column[data-align=center]{text-align:center}[dir=ltr] .k-structure-table .k-structure-table-column[data-align=right]{text-align:right}[dir=rtl] .k-structure-table .k-structure-table-column[data-align=right]{text-align:left}.k-structure-table .k-structure-table-column[data-width="1/2"]{width:50%}.k-structure-table .k-structure-table-column[data-width="1/3"]{width:33.33%}.k-structure-table .k-structure-table-column[data-width="1/4"]{width:25%}.k-structure-table .k-structure-table-column[data-width="1/5"]{width:20%}.k-structure-table .k-structure-table-column[data-width="1/6"]{width:16.66%}.k-structure-table .k-structure-table-column[data-width="1/8"]{width:12.5%}.k-structure-table .k-structure-table-column[data-width="1/9"]{width:11.11%}.k-structure-table .k-structure-table-column[data-width="2/3"]{width:66.66%}.k-structure-table .k-structure-table-column[data-width="3/4"]{width:75%}.k-structure-table .k-structure-table-index{width:38px;text-align:center}.k-structure-table .k-structure-table-index-number{font-size:.75rem;color:#999;padding-top:.15rem}.k-structure-table .k-sort-handle{width:38px;height:38px;display:none}.k-structure-table[data-sortable] tr:hover .k-structure-table-index-number{display:none}.k-structure-table[data-sortable] tr:hover .k-sort-handle{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.k-structure-table .k-structure-table-option{width:38px;text-align:center}.k-structure-table .k-structure-table-option .k-button{width:38px;height:38px}.k-structure-table .k-structure-table-text{padding:0 .75rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.k-structure-table .k-sortable-ghost{background:#fff;-webkit-box-shadow:rgba(22,23,26,.25) 0 5px 10px;box-shadow:0 5px 10px rgba(22,23,26,.25);outline:2px solid #4271ae;margin-bottom:2px;cursor:-webkit-grabbing}.k-sortable-row-fallback{opacity:0!important}.k-structure-backdrop{position:absolute;top:0;right:0;bottom:0;left:0;z-index:2;height:100vh}.k-structure-form{position:relative;z-index:3;border-radius:1px;margin-bottom:1px;-webkit-box-shadow:rgba(22,23,26,.05) 0 0 0 3px;box-shadow:0 0 0 3px rgba(22,23,26,.05);border:1px solid #ccc;background:#efefef}.k-structure-form-fields{padding:1.5rem 1.5rem 2rem}.k-structure-form-buttons{border-top:1px solid #ccc;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.k-structure-form-buttons .k-pagination{display:none}@media screen and (min-width:65em){.k-structure-form-buttons .k-pagination{display:-webkit-box;display:-ms-flexbox;display:flex}}.k-structure-form-buttons .k-pagination>.k-button,.k-structure-form-buttons .k-pagination>span{padding:.875rem 1rem!important}.k-structure-form-cancel-button,.k-structure-form-submit-button{padding:.875rem 1.5rem;line-height:1rem;display:-webkit-box;display:-ms-flexbox;display:flex}.k-field-counter{display:none}.k-text-field:focus-within .k-field-counter{display:block}.k-users-field[data-disabled] *{pointer-events:all!important}.k-toolbar{background:#fff;border-bottom:1px solid #efefef;height:38px}.k-toolbar-wrapper{position:absolute;top:0;right:0;left:0;max-width:100%}.k-toolbar-buttons{display:-webkit-box;display:-ms-flexbox;display:flex}.k-toolbar-divider{width:1px;background:#efefef}.k-toolbar-button{width:36px;height:36px}.k-toolbar-button:hover{background:hsla(0,0%,93.7%,.5)}.k-files-field-preview{display:grid;grid-gap:.5rem;grid-template-columns:repeat(auto-fill,1.525rem);padding:0 .75rem}.k-files-field-preview li{line-height:0}.k-files-field-preview li .k-icon{height:100%}.k-url-field-preview{padding:0 .75rem}.k-url-field-preview a{color:#4271ae;text-decoration:underline;-webkit-transition:color .3s;transition:color .3s;overflow:hidden;white-space:nowrap;max-width:100%;text-overflow:ellipsis}.k-url-field-preview a:hover{color:#000}.k-pages-field-preview{padding:0 .25rem 0 .75rem;display:-webkit-box;display:-ms-flexbox;display:flex}.k-pages-field-preview li{line-height:0;margin-right:.5rem}.k-pages-field-preview .k-link{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;background:#efefef;-webkit-box-shadow:rgba(22,23,26,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(22,23,26,.05)}.k-pages-field-preview-image{width:1.525rem;height:1.525rem;color:#999!important}.k-pages-field-preview figcaption{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;line-height:1.5em;padding:0 .5rem;border:1px solid #ccc;border-left:0;border-radius:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.k-users-field-preview{padding:0 .25rem 0 .75rem;display:-webkit-box;display:-ms-flexbox;display:flex}.k-users-field-preview li{line-height:0;margin-right:.5rem}.k-users-field-preview .k-link{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;background:#efefef;-webkit-box-shadow:rgba(22,23,26,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(22,23,26,.05)}.k-users-field-preview-avatar{width:1.525rem;height:1.525rem;color:#999!important}.k-users-field-preview-avatar.k-image{display:block}.k-users-field-preview figcaption{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;line-height:1.5em;padding:0 .5rem;border:1px solid #ccc;border-left:0;border-radius:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.k-bar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;line-height:1}.k-bar-slot{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.k-bar-slot[data-position=center]{text-align:center}[dir=ltr] .k-bar-slot[data-position=right]{text-align:right}[dir=rtl] .k-bar-slot[data-position=right]{text-align:left}.k-box{background:#d9d9d9;border-radius:1px;padding:.375rem .75rem;line-height:1.25rem;border-left:2px solid #999;padding:.5rem 1.5rem;word-wrap:break-word;font-size:.875rem}.k-box[data-theme=code]{background:#16171a;border:1px solid #000;color:#efefef;font-family:Input,Menlo,monospace;font-size:.875rem;line-height:1.5}.k-box[data-theme=button]{padding:0}.k-box[data-theme=button] .k-button{padding:0 .75rem;height:2.25rem;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:2rem;text-align:left}.k-box[data-theme=positive]{background:#dbe4c1;border:0;border-left:2px solid #a7bd68;padding:.5rem 1.5rem}.k-box[data-theme=negative]{background:#eec6c6;border:0;border-left:2px solid #d16464;padding:.5rem 1.5rem}.k-box[data-theme=notice]{background:#f4dac9;border:0;border-left:2px solid #de935f;padding:.5rem 1.5rem}.k-box[data-theme=info]{background:#d5e0e9;border:0;border-left:2px solid #81a2be;padding:.5rem 1.5rem}.k-box[data-theme=empty]{text-align:center;border-left:0;padding:3rem 1.5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background:#efefef;border-radius:1px;color:#777;border:1px dashed #ccc}.k-box[data-theme=empty] .k-icon{margin-bottom:.5rem;color:#999}.k-box[data-theme=empty] p{color:#777}.k-card{position:relative;border-radius:1px;-webkit-box-shadow:rgba(22,23,26,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(22,23,26,.05)}.k-card,.k-card a{min-width:0;background:#fff}.k-card:focus-within{-webkit-box-shadow:#4271ae 0 0 0 2px;box-shadow:0 0 0 2px #4271ae}.k-card a:focus{outline:0}.k-card .k-sort-handle{position:absolute;top:.75rem;width:2rem;height:2rem;border-radius:1px;background:#fff;opacity:0;color:#16171a;z-index:1;will-change:opacity;-webkit-transition:opacity .3s;transition:opacity .3s}[dir=ltr] .k-card .k-sort-handle{right:.75rem}[dir=rtl] .k-card .k-sort-handle{left:.75rem}.k-cards:hover .k-sort-handle{opacity:.25}.k-card:hover .k-sort-handle{opacity:1}.k-card.k-sortable-ghost{outline:2px solid #4271ae;border-radius:0}.k-card-icon,.k-card-image{border-top-left-radius:1px;border-top-right-radius:1px;overflow:hidden}.k-card-icon{position:relative;display:block}.k-card-icon .k-icon{position:absolute;top:0;right:0;bottom:0;left:0}.k-card-icon .k-icon-emoji{font-size:3rem}.k-card-icon .k-icon svg{width:3rem;height:3rem}.k-card-content{line-height:1.25rem;border-bottom-left-radius:1px;border-bottom-right-radius:1px;min-height:2.25rem;padding:.5rem .75rem;overflow-wrap:break-word;word-wrap:break-word}.k-card-text{display:block;font-weight:400;text-overflow:ellipsis;font-size:.875rem}.k-card-text[data-noinfo]:after{content:" ";height:1em;width:5rem;display:inline-block}.k-card-info{color:#777;display:block;font-size:.875rem;text-overflow:ellipsis;overflow:hidden}[dir=ltr] .k-card-info{margin-right:4rem}[dir=rtl] .k-card-info{margin-left:4rem}.k-card-options{position:absolute;bottom:0}[dir=ltr] .k-card-options{right:0}[dir=rtl] .k-card-options{left:0}.k-card-options>.k-button{position:relative;float:left;height:2.25rem;padding:0 .75rem;line-height:1}.k-card-options-dropdown{top:2.25rem}.k-cards{display:grid;grid-gap:1.5rem;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr))}@media screen and (min-width:30em){.k-cards[data-size=tiny]{grid-template-columns:repeat(auto-fill,minmax(12rem,1fr))}.k-cards[data-size=small]{grid-template-columns:repeat(auto-fill,minmax(16rem,1fr))}.k-cards[data-size=medium]{grid-template-columns:repeat(auto-fill,minmax(24rem,1fr))}.k-cards[data-size=huge],.k-cards[data-size=large]{grid-template-columns:1fr}}@media screen and (min-width:65em){.k-cards[data-size=large]{grid-template-columns:repeat(auto-fill,minmax(32rem,1fr))}}.k-collection-help{padding:.5rem .75rem}.k-collection-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin-right:-.75rem;margin-left:-.75rem}.k-collection-pagination{line-height:1.25rem;min-height:2.75rem}.k-collection-pagination .k-pagination .k-button{padding:.5rem .75rem;line-height:1.125rem}.k-column{min-width:0;grid-column-start:span 12}@media screen and (min-width:65em){.k-column[data-width="1/1"],.k-column[data-width="2/2"],.k-column[data-width="3/3"],.k-column[data-width="4/4"],.k-column[data-width="6/6"]{grid-column-start:span 12}.k-column[data-width="1/2"],.k-column[data-width="2/4"],.k-column[data-width="3/6"]{grid-column-start:span 6}.k-column[data-width="1/3"],.k-column[data-width="2/6"]{grid-column-start:span 4}.k-column[data-width="2/3"],.k-column[data-width="4/6"]{grid-column-start:span 8}.k-column[data-width="1/4"]{grid-column-start:span 3}.k-column[data-width="1/6"]{grid-column-start:span 2}.k-column[data-width="5/6"]{grid-column-start:span 10}.k-column[data-width="3/4"]{grid-column-start:span 9}}.k-dropzone{position:relative}.k-dropzone:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;display:none;pointer-events:none;z-index:1}.k-dropzone[data-over]:after{display:block;outline:1px solid #4271ae;-webkit-box-shadow:rgba(66,113,174,.25) 0 0 0 3px;box-shadow:0 0 0 3px rgba(66,113,174,.25)}.k-empty{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;border-radius:1px;color:#777;border:1px dashed #ccc}.k-empty p{font-size:.875rem;color:#777}.k-empty>.k-icon{color:#999}.k-empty[data-layout=cards]{text-align:center;padding:1.5rem;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.k-empty[data-layout=cards] .k-icon{margin-bottom:1rem}.k-empty[data-layout=cards] .k-icon svg{width:2rem;height:2rem}.k-empty[data-layout=list]{min-height:38px}.k-empty[data-layout=list]>.k-icon{width:36px;min-height:36px;border-right:1px solid rgba(0,0,0,.05)}.k-empty[data-layout=list]>p{line-height:1.25rem;padding:.5rem .75rem}.k-file-preview{background:#2d2f36}.k-file-preview-layout{display:grid}@media screen and (max-width:65em){.k-file-preview-layout{padding:0!important}}@media screen and (min-width:30em){.k-file-preview-layout{grid-template-columns:50% auto}}@media screen and (min-width:65em){.k-file-preview-layout{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}}.k-file-preview-layout>*{min-width:0}.k-file-preview-image{position:relative;background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXR0ZXJuIGlkPSJhIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiPjxwYXRoIGZpbGw9InJnYmEoMCwgMCwgMCwgMC4yKSIgZD0iTTAgMGgxMHYxMEgwem0xMCAxMGgxMHYxMEgxMHoiLz48L3BhdHRlcm4+PHJlY3QgZmlsbD0idXJsKCNhKSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIvPjwvc3ZnPg==")}@media screen and (min-width:65em){.k-file-preview-image{width:33.33%}}@media screen and (min-width:90em){.k-file-preview-image{width:25%}}.k-file-preview-image .k-image span{overflow:hidden;padding-bottom:66.66%}@media screen and (min-width:30em) and (max-width:65em){.k-file-preview-image .k-image span{position:absolute;top:0;left:0;bottom:0;right:0;padding-bottom:0!important}}@media screen and (min-width:65em){.k-file-preview-image .k-image span{padding-bottom:100%}}.k-file-preview-placeholder{display:block;padding-bottom:100%}.k-file-preview-image img{padding:3rem}.k-file-preview-image-link{display:block;outline:0}.k-file-preview-image-link[data-tabbed]{outline:2px solid #4271ae!important;outline-offset:-2px}.k-file-preview-icon{position:relative;display:block;padding-bottom:100%;overflow:hidden;color:hsla(0,0%,100%,.5)}.k-file-preview-icon svg{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%) scale(4);transform:translate(-50%,-50%) scale(4)}.k-file-preview-details{padding:1.5rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}@media screen and (min-width:65em){.k-file-preview-details{padding:3rem}}.k-file-preview-details ul{line-height:1.5em;max-width:50rem;display:grid;grid-gap:1.5rem 3rem;grid-template-columns:repeat(auto-fill,minmax(100px,1fr))}@media screen and (min-width:30em){.k-file-preview-details ul{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}.k-file-preview-details h3{font-size:.875rem;font-weight:500;color:#999}.k-file-preview-details p{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:hsla(0,0%,100%,.75);font-size:.875rem}.k-file-preview-details p a{display:block;width:100%;overflow:hidden;text-overflow:ellipsis}.k-grid{--columns:12;display:grid;grid-column-gap:0;grid-row-gap:0;grid-template-columns:1fr}@media screen and (min-width:30em){.k-grid[data-gutter=small]{grid-column-gap:1rem;grid-row-gap:1rem}.k-grid[data-gutter=huge],.k-grid[data-gutter=large],.k-grid[data-gutter=medium]{grid-column-gap:1.5rem;grid-row-gap:1.5rem}}@media screen and (min-width:65em){.k-grid{grid-template-columns:repeat(var(--columns),1fr)}.k-grid[data-gutter=large]{grid-column-gap:3rem}.k-grid[data-gutter=huge]{grid-column-gap:4.5rem}}@media screen and (min-width:90em){.k-grid[data-gutter=large]{grid-column-gap:4.5rem}.k-grid[data-gutter=huge]{grid-column-gap:6rem}}@media screen and (min-width:120em){.k-grid[data-gutter=large]{grid-column-gap:6rem}.k-grid[data-gutter=huge]{grid-column-gap:7.5rem}}.k-header{border-bottom:1px solid #ccc;margin-bottom:2rem;padding-top:4vh}.k-header .k-headline{min-height:1.25em;margin-bottom:.5rem}.k-header .k-header-buttons{margin-top:-.5rem;height:3.25rem}.k-header .k-headline-editable{cursor:pointer}.k-header .k-headline-editable .k-icon{color:#999;opacity:0;-webkit-transition:opacity .3s;transition:opacity .3s;display:inline-block}[dir=ltr] .k-header .k-headline-editable .k-icon{margin-left:.5rem}[dir=rtl] .k-header .k-headline-editable .k-icon{margin-right:.5rem}.k-header .k-headline-editable:hover .k-icon{opacity:1}.k-header-tabs{position:relative;background:#e9e9e9;border-top:1px solid #ccc;border-left:1px solid #ccc;border-right:1px solid #ccc}.k-header-tabs nav{display:-webkit-box;display:-ms-flexbox;display:flex;margin-left:-1px;margin-right:-1px}.k-header-tabs nav,.k-tab-button.k-button{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.k-tab-button.k-button{position:relative;z-index:1;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:.625rem .75rem;font-size:.75rem;text-transform:uppercase;text-align:center;font-weight:500;border-left:1px solid transparent;border-right:1px solid #ccc;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-width:15rem}@media screen and (min-width:30em){.k-tab-button.k-button{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}}@media screen and (min-width:30em){.k-tab-button.k-button .k-icon{margin-right:.5rem}}.k-tab-button.k-button>.k-button-text{padding-top:.375rem;font-size:10px;overflow:hidden;max-width:10rem;text-overflow:ellipsis}[dir=ltr] .k-tab-button.k-button>.k-button-text{padding-left:0}[dir=rtl] .k-tab-button.k-button>.k-button-text{padding-right:0}@media screen and (min-width:30em){.k-tab-button.k-button>.k-button-text{font-size:.75rem;padding-top:0}}.k-tab-button:last-child{border-right:1px solid transparent}.k-tab-button[aria-current]{position:relative;background:#efefef;border-right:1px solid #ccc;pointer-events:none}.k-tab-button[aria-current]:first-child{border-left:1px solid #ccc}.k-tab-button[aria-current]:after,.k-tab-button[aria-current]:before{position:absolute;content:""}.k-tab-button[aria-current]:before{left:-1px;right:-1px;height:2px;top:-1px;background:#16171a}.k-tab-button[aria-current]:after{left:0;right:0;height:1px;bottom:-1px;background:#efefef}.k-tabs-dropdown{top:100%;right:0}.k-list .k-list-item:not(:last-child){margin-bottom:2px}.k-list-item{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#fff;border-radius:1px;-webkit-box-shadow:rgba(22,23,26,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(22,23,26,.05)}.k-list-item .k-sort-handle{position:absolute;left:-1.5rem;width:1.5rem;height:38px;opacity:0}.k-list:hover .k-sort-handle{opacity:.25}.k-list-item:hover .k-sort-handle{opacity:1}.k-list-item.k-sortable-ghost{position:relative;outline:2px solid #4271ae;z-index:1;-webkit-box-shadow:rgba(22,23,26,.25) 0 5px 10px;box-shadow:0 5px 10px rgba(22,23,26,.25)}.k-list-item.k-sortable-fallback{opacity:.25!important;overflow:hidden}.k-list-item-image{width:38px;height:38px;overflow:hidden;-ms-flex-negative:0;flex-shrink:0;line-height:0}.k-list-item-image .k-image{width:38px;height:38px;-o-object-fit:contain;object-fit:contain}.k-list-item-image .k-icon{width:38px;height:38px}.k-list-item-image .k-icon svg{opacity:.5}.k-list-item-content{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1;overflow:hidden;outline:none}.k-list-item-content[data-tabbed]{outline:none;-webkit-box-shadow:#4271ae 0 0 0 2px,rgba(66,113,174,.2) 0 0 0 2px;box-shadow:0 0 0 2px #4271ae,0 0 0 2px rgba(66,113,174,.2)}.k-list-item-text{display:-webkit-box;display:-ms-flexbox;display:flex;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;width:100%;line-height:1.25rem;padding:.5rem .75rem}.k-list-item-text em{font-style:normal;margin-right:1rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:.875rem;color:#16171a}.k-list-item-text em,.k-list-item-text small{min-width:0;overflow:hidden;text-overflow:ellipsis}.k-list-item-text small{color:#999;font-size:.75rem;color:#777;display:none}@media screen and (min-width:30em){.k-list-item-text small{display:block}}.k-list-item-options{position:relative;-ms-flex-negative:0;flex-shrink:0}.k-list-item-options .k-dropdown-content{top:38px}.k-list-item-options>.k-button{height:38px;padding:0 12px}.k-list-item-options>.k-button>.k-button-icon{height:38px}.k-view{padding-left:1.5rem;padding-right:1.5rem;margin:0 auto;max-width:100rem}@media screen and (min-width:30em){.k-view{padding-left:3rem;padding-right:3rem}}@media screen and (min-width:90em){.k-view{padding-left:6rem;padding-right:6rem}}.k-view[data-align=center]{height:calc(100vh - 6rem);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:0 3rem;overflow:auto}.k-view[data-align=center]>*{-ms-flex-preferred-size:22.5rem;flex-basis:22.5rem}.k-headline{font-size:1rem;font-weight:600;line-height:1.5em}.k-headline[data-size=small]{font-size:.875rem}.k-headline[data-size=large]{font-size:1.25rem;font-weight:400}@media screen and (min-width:65em){.k-headline[data-size=large]{font-size:1.5rem}}.k-headline[data-size=huge]{font-size:1.5rem;line-height:1.15em}@media screen and (min-width:65em){.k-headline[data-size=huge]{font-size:1.75rem}}.k-headline[data-theme=negative]{color:#c82829}.k-headline[data-theme=positive]{color:#5d800d}.k-headline abbr{color:#999;padding-left:.25rem;text-decoration:none}.k-icon{position:relative;line-height:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-ms-flex-negative:0;flex-shrink:0}.k-icon svg{width:1rem;height:1rem;-moz-transform:scale(1)}.k-icon svg *{fill:currentColor}.k-icon[data-back=black]{background:#16171a;color:#fff}.k-icon[data-back=white]{background:#fff;color:#16171a}.k-icon[data-back=pattern]{background:#2d2f36 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXR0ZXJuIGlkPSJhIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiPjxwYXRoIGZpbGw9InJnYmEoMCwgMCwgMCwgMC4yKSIgZD0iTTAgMGgxMHYxMEgwem0xMCAxMGgxMHYxMEgxMHoiLz48L3BhdHRlcm4+PHJlY3QgZmlsbD0idXJsKCNhKSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIvPjwvc3ZnPg==");color:#fff}.k-icon[data-size=medium] svg{width:2rem;height:2rem}.k-icon[data-size=large] svg{width:3rem;height:3rem}.k-icon-emoji{display:block;line-height:1;font-style:normal;font-size:1rem}@media not all,only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.k-icon-emoji{font-size:1.25rem;margin-left:.2rem}}.k-image span{position:relative;display:block;line-height:0;padding-bottom:100%}.k-image img{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;-o-object-fit:contain;object-fit:contain}.k-image-error{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#fff;font-size:.9em}.k-image-error svg *{fill:hsla(0,0%,100%,.3)}.k-image[data-cover] img{-o-object-fit:cover;object-fit:cover}.k-image[data-back=black] span{background:#16171a}.k-image[data-back=white] span{background:#fff;color:#16171a}.k-image[data-back=white] .k-image-error{background:#16171a;color:#fff}.k-image[data-back=pattern] span{background:#2d2f36 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXR0ZXJuIGlkPSJhIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiPjxwYXRoIGZpbGw9InJnYmEoMCwgMCwgMCwgMC4yKSIgZD0iTTAgMGgxMHYxMEgwem0xMCAxMGgxMHYxMEgxMHoiLz48L3BhdHRlcm4+PHJlY3QgZmlsbD0idXJsKCNhKSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIvPjwvc3ZnPg==")}.k-progress{-webkit-appearance:none;width:100%;height:.5rem;border-radius:5rem}.k-progress::-webkit-progress-bar{border:none;background:#ccc;height:.5rem;border-radius:20px}.k-progress::-webkit-progress-value{border-radius:20px;background:#4271ae;-webkit-transition:width .3s;transition:width .3s}.k-sort-handle{cursor:-webkit-grab;color:#16171a;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:0;width:2rem;height:2rem;display:-webkit-box;display:-ms-flexbox;display:flex;will-change:opacity,color;-webkit-transition:opacity .3s;transition:opacity .3s;z-index:1}.k-sort-handle svg{width:1rem}.k-sort-handle:active{cursor:-webkit-grabbing}.k-text{line-height:1.5em}.k-text p{margin-bottom:1.5em}.k-text a{text-decoration:underline}.k-text>:last-child{margin-bottom:0}.k-text[data-align=center]{text-align:center}.k-text[data-align=right]{text-align:right}.k-text[data-size=tiny]{font-size:.75rem}.k-text[data-size=small]{font-size:.875rem}.k-text[data-size=medium]{font-size:1rem}.k-text[data-size=large]{font-size:1.25rem}.k-text[data-theme=help]{font-size:.875rem;color:#777;line-height:1.25rem}button{line-height:inherit;border:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;font-size:1rem;color:currentColor;background:none;cursor:pointer}button::-moz-focus-inner{padding:0;border:0}.k-button[data-disabled],.k-button[disabled]{pointer-events:none;opacity:.5}.k-button{display:inline-block;position:relative;font-size:.875rem;-webkit-transition:color .3s;transition:color .3s}.k-button,.k-button:focus,.k-button:hover{outline:none}.k-button[data-tabbed]{outline:none;-webkit-box-shadow:#4271ae 0 0 0 2px,rgba(66,113,174,.2) 0 0 0 2px;box-shadow:0 0 0 2px #4271ae,0 0 0 2px rgba(66,113,174,.2)}.k-button *{vertical-align:middle}.k-button[data-responsive] .k-button-text{display:none}@media screen and (min-width:30em){.k-button[data-responsive] .k-button-text{display:inline}}.k-button[data-theme=positive]{color:#5d800d}.k-button[data-theme=negative]{color:#c82829}.k-button-icon{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:0}[dir=ltr] .k-button-icon~.k-button-text{padding-left:.5rem}[dir=rtl] .k-button-icon~.k-button-text{padding-right:.5rem}.k-button-text{opacity:.75}.k-button:focus .k-button-text,.k-button:hover .k-button-text{opacity:1}.k-button-text b,.k-button-text span{vertical-align:baseline}.k-button-group{font-size:0;margin-left:-.75rem;margin-right:-.75rem}.k-button-group>.k-dropdown{height:3rem;display:inline-block}.k-button-group>.k-button,.k-button-group>.k-dropdown>.k-button{padding:1rem .75rem;line-height:1rem}.k-button-group .k-dropdown-content{top:calc(100% + 1px);margin:0 .75rem}.k-dropdown{position:relative}.k-dropdown-content{position:absolute;top:100%;background:#16171a;color:#fff;z-index:700;-webkit-box-shadow:rgba(22,23,26,.2) 0 2px 10px;box-shadow:0 2px 10px rgba(22,23,26,.2);border-radius:1px;text-align:left}[dir=ltr] .k-dropdown-content{left:0}[dir=rtl] .k-dropdown-content{right:0}[dir=ltr] .k-dropdown-content[data-align=right]{left:auto;right:0}[dir=rtl] .k-dropdown-content[data-align=right]{left:0;right:auto}.k-dropdown-content>.k-dropdown-item:first-child{margin-top:.5rem}.k-dropdown-content>.k-dropdown-item:last-child{margin-bottom:.5rem}.k-dropdown-content hr{position:relative;padding:.5rem 0;border:0}.k-dropdown-content hr:after{position:absolute;top:.5rem;left:1rem;right:1rem;content:"";height:1px;background:currentColor;opacity:.2}.k-dropdown-item{white-space:nowrap;line-height:1;display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:.875rem;padding:6px 16px}.k-dropdown-item:focus{outline:none;-webkit-box-shadow:#4271ae 0 0 0 2px,rgba(66,113,174,.2) 0 0 0 2px;box-shadow:0 0 0 2px #4271ae,0 0 0 2px rgba(66,113,174,.2)}.k-dropdown-item .k-button-figure{text-align:center;padding-right:.5rem}.k-pagination{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;direction:ltr}.k-pagination .k-button{padding:1rem}.k-pagination-details{white-space:nowrap}.k-pagination>span{font-size:.875rem}.k-pagination[data-align=center]{text-align:center}.k-pagination[data-align=right]{text-align:right}.k-dropdown-content.k-pagination-selector{position:absolute;top:100%;left:50%;width:14rem;margin-left:-7rem;background:#000}[dir=ltr] .k-dropdown-content.k-pagination-selector{direction:ltr}[dir=rtl] .k-dropdown-content.k-pagination-selector{direction:rtl}.k-pagination-selector>div{font-size:.875rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-pagination-selector .k-button{padding:.75rem 1rem;line-height:1}.k-pagination-selector>div>label{padding:.75rem 1rem}.k-pagination-selector>div>input{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font:inherit;border:0;padding:.75rem 1rem;color:#fff;background:none;text-align:center;border-left:1px solid hsla(0,0%,100%,.2);border-right:1px solid hsla(0,0%,100%,.2)}.k-pagination-selector>div>input:focus{outline:0}.k-prev-next{direction:ltr}.k-search{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;overflow:auto;background:rgba(22,23,26,.6)}.k-search-box{max-width:30rem;margin:0 auto;-webkit-box-shadow:rgba(22,23,26,.2) 0 2px 10px;box-shadow:0 2px 10px rgba(22,23,26,.2)}@media screen and (min-width:65em){.k-search-box{margin:2.5rem auto}}.k-search-input{background:#efefef}.k-search-input,.k-search-types{display:-webkit-box;display:-ms-flexbox;display:flex}.k-search-types{-ms-flex-negative:0;flex-shrink:0}.k-search-types>.k-button{padding:0 0 0 .7rem;font-size:1rem;line-height:1;height:2.5rem}.k-search-types>.k-button .k-icon{height:2.5rem}.k-search-types>.k-button .k-button-text{opacity:1;font-weight:500}.k-search-input input{background:none;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font:inherit;padding:.75rem;border:0;height:2.5rem}.k-search-close{width:2.5rem;line-height:1}.k-search input:focus{outline:0}.k-search ul{background:#fff}.k-search li{border-bottom:1px solid #efefef;line-height:1.125;display:-webkit-box;display:-ms-flexbox;display:flex}.k-search li .k-link{display:block;padding:.5rem .75rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.k-search li strong{display:block;font-size:.875rem;font-weight:400}.k-search li small{font-size:.75rem;color:#777}.k-search li[data-selected]{outline:2px solid #4271ae;background:rgba(66,113,174,.25);border-bottom:1px solid transparent}.k-search-empty{padding:.825rem .75rem;font-size:.75rem;background:#efefef;border-top:1px dashed #ccc;color:#777}.k-tag{position:relative;font-size:.875rem;line-height:1;cursor:pointer;background-color:#16171a;color:#efefef;border-radius:1px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.k-tag:focus{outline:0;background-color:#4271ae;border-color:#4271ae;color:#fff}.k-tag-text{padding:0 .75rem}.k-tag-toggle{color:hsla(0,0%,100%,.7);width:2rem;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-left:1px solid hsla(0,0%,100%,.15)}.k-tag-toggle:hover{background:hsla(0,0%,100%,.2);color:#fff}.k-topbar{position:relative;color:#fff;-ms-flex-negative:0;flex-shrink:0;height:2.5rem;line-height:1;background:#16171a}.k-topbar-wrapper{position:relative;margin-left:-.75rem;margin-right:-.75rem}.k-topbar-loader,.k-topbar-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-topbar-loader{position:absolute;top:0;right:0;bottom:0;height:2.5rem;width:2.5rem;padding:.75rem;background:#16171a;z-index:1;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.k-topbar-loader svg{height:18px;width:18px;-webkit-animation:Spin .9s linear infinite;animation:Spin .9s linear infinite}.k-topbar-menu{-ms-flex-negative:0;flex-shrink:0}.k-topbar-menu ul{padding:.5rem 0}.k-topbar-menu-button{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-topbar-menu-button .k-button-text{opacity:1}.k-topbar-button,.k-topbar-signals-button{padding:.75rem;line-height:1;font-size:.875rem}.k-topbar-signals .k-button .k-button-text{opacity:1}.k-topbar-button .k-button-text{display:-webkit-box;display:-ms-flexbox;display:flex;opacity:1}.k-topbar-view-button{-ms-flex-negative:0;flex-shrink:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;outline:none}.k-topbar-view-button[data-tabbed]{outline:none;-webkit-box-shadow:#4271ae 0 0 0 2px,rgba(66,113,174,.2) 0 0 0 2px;box-shadow:0 0 0 2px #4271ae,0 0 0 2px rgba(66,113,174,.2)}[dir=ltr] .k-topbar-view-button{padding-right:0}[dir=rtl] .k-topbar-view-button{padding-left:0}[dir=ltr] .k-topbar-view-button .k-icon{margin-right:.5rem}[dir=rtl] .k-topbar-view-button .k-icon{margin-left:.5rem}.k-topbar-crumbs{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-ms-flexbox;display:flex}.k-topbar-crumbs a{position:relative;font-size:.875rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:none;padding-top:.75rem;padding-bottom:.75rem;line-height:1;-webkit-transition:opacity .3s;transition:opacity .3s;outline:none}.k-topbar-crumbs a:before{content:"/";padding:0 .5rem;opacity:.25}.k-topbar-crumbs a:focus,.k-topbar-crumbs a:hover{opacity:1}.k-topbar-crumbs a[data-tabbed]{outline:none;-webkit-box-shadow:#4271ae 0 0 0 2px,rgba(66,113,174,.2) 0 0 0 2px;box-shadow:0 0 0 2px #4271ae,0 0 0 2px rgba(66,113,174,.2)}.k-topbar-crumbs a:not(:last-child){max-width:15vw}.k-topbar-breadcrumb-menu{-ms-flex-negative:0;flex-shrink:0}@media screen and (min-width:30em){.k-topbar-crumbs a{display:block}.k-topbar-breadcrumb-menu{display:none}}.k-topbar-signals{position:absolute;top:0;background:#16171a;height:2.5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}[dir=ltr] .k-topbar-signals{right:0}[dir=rtl] .k-topbar-signals{left:0}.k-topbar-signals:before{position:absolute;content:"";top:0;bottom:0;width:.5rem}[dir=ltr] .k-topbar-signals:before{left:-.5rem;background:-webkit-linear-gradient(left,rgba(22,23,26,0),#16171a)}[dir=rtl] .k-topbar-signals:before{right:-.5rem;background:-webkit-linear-gradient(right,rgba(22,23,26,0),#16171a)}.k-topbar-signals .k-button{line-height:1}.k-topbar-notification{font-weight:600;line-height:1;display:-webkit-box;display:-ms-flexbox;display:flex}.k-topbar .k-button[data-theme=positive]{color:#a7bd68}.k-topbar .k-button[data-theme=negative]{color:#d16464}.k-topbar .k-button[data-theme=negative] .k-button-text{display:none}@media screen and (min-width:30em){.k-topbar .k-button[data-theme=negative] .k-button-text{display:inline}}.k-topbar .k-button[data-theme] .k-button-text{opacity:1}.k-topbar .k-dropdown-content{color:#16171a;background:#fff}.k-topbar .k-dropdown-content hr:after{opacity:.1}.k-topbar-menu [aria-current] .k-link{color:#4271ae;font-weight:500}.k-registration{display:inline-block;margin-right:1rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-registration p{color:#d16464;font-size:.875rem;margin-right:1rem;font-weight:600;display:none}@media screen and (min-width:90em){.k-registration p{display:block}}.k-registration .k-button{color:#fff}.k-section,.k-sections{padding-bottom:3rem}.k-section-header{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;z-index:1}.k-section-header .k-headline{line-height:1.25rem;padding-bottom:.75rem;min-height:2rem}.k-section-header .k-button-group{position:absolute;top:-.875rem}[dir=ltr] .k-section-header .k-button-group{right:0}[dir=rtl] .k-section-header .k-button-group{left:0}.k-fields-issue-headline,.k-info-section-headline{margin-bottom:.5rem}.k-fields-section input[type=submit]{display:none}[data-locked] .k-fields-section{opacity:.2;pointer-events:none}.k-browser-view .k-error-view-content{text-align:left}.k-error-view{position:absolute;top:0;right:0;bottom:0;left:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.k-error-view-content{line-height:1.5em;max-width:25rem;text-align:center}.k-error-view-icon{color:#c82829;display:inline-block}.k-error-view-content p:not(:last-child){margin-bottom:.75rem}.k-installation-view .k-button{display:block;margin-top:1.5rem}.k-installation-view .k-headline{margin-bottom:.75rem}.k-installation-issues{line-height:1.5em;font-size:.875rem}.k-installation-issues li{position:relative;padding:1.5rem;background:#fff}[dir=ltr] .k-installation-issues li{padding-left:3.5rem}[dir=rtl] .k-installation-issues li{padding-right:3.5rem}.k-installation-issues .k-icon{position:absolute;top:calc(1.5rem + 2px)}[dir=ltr] .k-installation-issues .k-icon{left:1.5rem}[dir=rtl] .k-installation-issues .k-icon{right:1.5rem}.k-installation-issues .k-icon svg *{fill:#c82829}.k-installation-issues li:not(:last-child){margin-bottom:2px}.k-installation-issues li code{font:inherit;color:#c82829}.k-installation-view .k-button[type=submit]{padding:1rem}[dir=ltr] .k-installation-view .k-button[type=submit]{margin-left:-1rem}[dir=rtl] .k-installation-view .k-button[type=submit]{margin-right:-1rem}.k-login-form[data-invalid]{-webkit-animation:shake .5s linear;animation:shake .5s linear}.k-login-form[data-invalid] .k-field label{-webkit-animation:nope 2s linear;animation:nope 2s linear}.k-login-form label abbr{visibility:hidden}.k-login-buttons{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:1.5rem 0}.k-login-button{padding:.5rem 1rem;font-weight:500;-webkit-transition:opacity .3s;transition:opacity .3s}[dir=ltr] .k-login-button{margin-right:-1rem}[dir=rtl] .k-login-button{margin-left:-1rem}.k-login-button span{opacity:1}.k-login-button[disabled]{opacity:.25}.k-login-checkbox{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:.5rem 0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:.875rem;cursor:pointer}.k-login-checkbox .k-checkbox-text{opacity:.75;-webkit-transition:opacity .3s;transition:opacity .3s}.k-login-checkbox:focus span,.k-login-checkbox:hover span{opacity:1}@-webkit-keyframes nope{0%{color:#c82829}to{color:#16171a}}@keyframes nope{0%{color:#c82829}to{color:#16171a}}@-webkit-keyframes shake{8%,41%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}25%,58%{-webkit-transform:translateX(10px);transform:translateX(10px)}75%{-webkit-transform:translateX(-5px);transform:translateX(-5px)}92%{-webkit-transform:translateX(5px);transform:translateX(5px)}0%,to{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes shake{8%,41%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}25%,58%{-webkit-transform:translateX(10px);transform:translateX(10px)}75%{-webkit-transform:translateX(-5px);transform:translateX(-5px)}92%{-webkit-transform:translateX(5px);transform:translateX(5px)}0%,to{-webkit-transform:translateX(0);transform:translateX(0)}}.k-status-flag svg{width:14px;height:14px}.k-status-flag-listed .k-icon{color:#a7bd68}.k-status-flag-unlisted .k-icon{color:#81a2be}.k-status-flag-draft .k-icon{color:#d16464}.k-status-flag[disabled]{opacity:1}.k-settings-view section{margin-bottom:3rem}.k-settings-view .k-header{margin-bottom:1.5rem}.k-settings-view header{margin-bottom:.5rem;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.k-settings-view header,.k-system-info-box{display:-webkit-box;display:-ms-flexbox;display:flex}.k-system-info-box{background:#fff;padding:.75rem}.k-system-info-box li{-ms-flex-negative:0;flex-shrink:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0}.k-system-info-box dt{font-size:.875rem;color:#777;margin-bottom:.25rem}.k-system-unregistered{color:#c82829}.k-languages-section{margin-bottom:2rem}.k-user-profile{background:#fff}.k-user-profile>.k-view{padding-top:3rem;padding-bottom:3rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:0}.k-user-profile .k-button-group{overflow:hidden}[dir=ltr] .k-user-profile .k-button-group{margin-left:.75rem}[dir=rtl] .k-user-profile .k-button-group{margin-right:.75rem}.k-user-profile .k-button-group .k-button{display:block;padding-top:.25rem;padding-bottom:.25rem;overflow:hidden;white-space:nowrap}.k-user-profile .k-button-group .k-button[disabled]{opacity:1}.k-user-profile .k-dropdown-content{margin-top:.5rem;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.k-user-view-image .k-image{display:block;width:4rem;height:4rem;line-height:0}.k-user-view-image .k-button-text{opacity:1}.k-user-view-image .k-icon{width:4rem;height:4rem;background:#16171a;color:#999}.k-user-name-placeholder{color:#999;-webkit-transition:color .3s;transition:color .3s}.k-header[data-editable] .k-user-name-placeholder:hover{color:#16171a}
\ No newline at end of file
+*,:after,:before{margin:0;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}:root{--color-backdrop:rgba(22,23,26,0.6);--color-background:#efefef;--color-border:#ccc;--color-focus:#4271ae;--color-focus-light:#81a2be;--color-focus-outline:rgba(66,113,174,0.25);--color-negative:#c82829;--color-negative-light:#d16464;--color-negative-outline:rgba(200,40,41,0.25);--color-notice:#f5871f;--color-notice-light:#de935f;--color-positive:#5d800d;--color-positive-light:#a7bd68;--color-positive-outline:rgba(93,128,13,0.25);--color-text:#16171a;--color-text-light:#777;--font-family-mono:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;--font-family-sans:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--font-size-tiny:0.75rem;--font-size-small:0.875rem;--font-size-medium:1rem;--font-size-large:1.25rem;--font-size-huge:1.5rem;--font-size-monster:1.75rem;--box-shadow-dropdown:rgba(22,23,26,0.2) 0 2px 10px;--box-shadow-item:rgba(22,23,26,0.05) 0 2px 5px;--box-shadow-focus:#4271ae 0 0 0 2px,rgba(66,113,174,0.2) 0 0 0 2px}noscript{padding:1.5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;height:100vh;text-align:center}html{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;background:#efefef}body,html{color:#16171a;overflow:hidden;height:100%}a{color:inherit;text-decoration:none}li{list-style:none}b,strong{font-weight:600}.fade-enter-active,.fade-leave-active{-webkit-transition:opacity .5s;transition:opacity .5s}.fade-enter,.fade-leave-to{opacity:0}.k-panel{position:absolute;top:0;right:0;bottom:0;left:0;background:#efefef}.k-panel[data-loading]{-webkit-animation:LoadingCursor .5s;animation:LoadingCursor .5s}.k-panel-header{position:absolute;top:0;left:0;right:0;z-index:300}.k-panel .k-form-buttons{position:fixed;bottom:0;left:0;right:0;z-index:300}.k-panel-view{position:absolute;top:0;right:0;bottom:0;left:0;padding-bottom:6rem;overflow-y:scroll;-webkit-overflow-scrolling:touch;-webkit-transform:translateZ(0);transform:translateZ(0)}.k-panel[data-dialog] .k-panel-view{overflow:hidden;-webkit-transform:none;transform:none}.k-panel[data-topbar] .k-panel-view{top:2.5rem}.k-panel[data-dragging],.k-panel[data-loading]:after{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.k-offline-warning{position:fixed;content:" ";top:0;right:0;bottom:0;left:0;z-index:900;background:rgba(22,23,26,.7);content:"offline";display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;color:#fff}@-webkit-keyframes LoadingCursor{to{cursor:progress}}@keyframes LoadingCursor{to{cursor:progress}}@-webkit-keyframes Spin{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes Spin{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.k-offscreen{-webkit-clip-path:inset(100%);clip-path:inset(100%);clip:rect(1px,1px,1px,1px);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}.k-icons{position:absolute;width:0;height:0}[data-invalid]{border:1px solid rgba(200,40,41,.25);-webkit-box-shadow:rgba(200,40,41,.25) 0 0 3px 2px;box-shadow:0 0 3px 2px rgba(200,40,41,.25)}[data-invalid]:focus-within{border:1px solid #c82829!important;-webkit-box-shadow:rgba(200,40,41,.25) 0 0 0 2px!important;box-shadow:0 0 0 2px rgba(200,40,41,.25)!important}.k-dialog{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:fixed;top:0;right:0;bottom:0;left:0;border:0;width:100%;height:100%;background:rgba(22,23,26,.6);z-index:600;-webkit-transform:translateZ(0);transform:translateZ(0)}.k-dialog,.k-dialog-box{display:-webkit-box;display:-ms-flexbox;display:flex}.k-dialog-box{position:relative;background:#efefef;width:22rem;-webkit-box-shadow:rgba(22,23,26,.2) 0 2px 10px;box-shadow:0 2px 10px rgba(22,23,26,.2);border-radius:1px;line-height:1;max-height:calc(100vh - 3rem);margin:1.5rem;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.k-dialog-box[data-size=small]{width:20rem}.k-dialog-box[data-size=medium]{width:30rem}.k-dialog-box[data-size=large]{width:40rem}.k-dialog-notification{padding:.75rem 1.5rem;background:#16171a;width:100%;line-height:1.25rem;color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-dialog-notification[data-theme=error]{background:#d16464;color:#000}.k-dialog-notification[data-theme=success]{background:#a7bd68;color:#000}.k-dialog-notification p{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;word-wrap:break-word;overflow:hidden}.k-dialog-notification .k-button{display:-webkit-box;display:-ms-flexbox;display:flex;margin-left:1rem}.k-dialog-body{padding:1.5rem;overflow-y:auto;overflow-x:hidden}.k-dialog-body .k-fieldset{padding-bottom:.5rem}.k-dialog-footer{border-top:1px solid #ccc;padding:0;border-bottom-left-radius:1px;border-bottom-right-radius:1px;line-height:1;-ms-flex-negative:0;flex-shrink:0}.k-dialog-footer .k-button-group{display:-webkit-box;display:-ms-flexbox;display:flex;margin:0;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.k-dialog-footer .k-button-group .k-button{padding:.75rem 1rem;line-height:1.25rem}.k-dialog-footer .k-button-group .k-button:first-child{text-align:left;padding-left:1.5rem}.k-dialog-footer .k-button-group .k-button:last-child{text-align:right;padding-right:1.5rem}.k-dialog-pagination{margin-bottom:-1.5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-dialog-search{margin-bottom:.75rem}.k-dialog-search.k-input{background:rgba(0,0,0,.075);padding:0 1rem;height:36px;border-radius:1px}.k-error-details{background:#fff;display:block;overflow:auto;padding:1rem;font-size:.875rem;line-height:1.25em;margin-top:.75rem}.k-error-details dt{color:#d16464;margin-bottom:.25rem}.k-error-details dd{overflow:hidden;overflow-wrap:break-word;text-overflow:ellipsis}.k-error-details dd:not(:last-of-type){margin-bottom:1.5em}.k-error-details li:not(:last-child){border-bottom:1px solid #efefef;padding-bottom:.25rem;margin-bottom:.25rem}.k-files-dialog .k-list-item{cursor:pointer}.k-page-remove-warning{margin:1.5rem 0}.k-page-remove-warning .k-box{font-size:1rem;line-height:1.5em;padding-top:.75rem;padding-bottom:.75rem}.k-pages-dialog-navbar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-bottom:.5rem;padding-right:38px}.k-pages-dialog-navbar .k-button{width:38px}.k-pages-dialog-navbar .k-button[disabled]{opacity:0}.k-pages-dialog-navbar .k-headline{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.k-pages-dialog .k-list-item{cursor:pointer}.k-pages-dialog .k-list-item .k-button[data-theme=disabled],.k-pages-dialog .k-list-item .k-button[disabled]{opacity:.25}.k-pages-dialog .k-list-item .k-button[data-theme=disabled]:hover{opacity:1}.k-users-dialog .k-list-item{cursor:pointer}.k-calendar-input{padding:.5rem;background:#16171a;color:#efefef;border-radius:1px}.k-calendar-table{table-layout:fixed;width:100%;min-width:15rem;padding-top:.5rem}.k-calendar-input>nav{display:-webkit-box;display:-ms-flexbox;display:flex;direction:ltr}.k-calendar-input>nav .k-button{padding:.5rem}.k-calendar-selects{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}[dir=ltr] .k-calendar-selects{direction:ltr}[dir=rtl] .k-calendar-selects{direction:rtl}.k-calendar-selects .k-select-input{padding:0 .5rem;font-weight:400;font-size:.875rem}.k-calendar-selects .k-select-input:focus-within{color:#81a2be!important}.k-calendar-input th{padding:.5rem 0;color:#999;font-size:.75rem;font-weight:400;text-align:center}.k-calendar-day .k-button{width:2rem;height:2rem;margin:0 auto;color:#fff;line-height:1.75rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:50%;border:2px solid transparent}.k-calendar-day .k-button .k-button-text{opacity:1}.k-calendar-table .k-button:hover{color:#fff}.k-calendar-day:hover .k-button{border-color:hsla(0,0%,100%,.25)}.k-calendar-day[aria-current=date] .k-button{color:#81a2be;font-weight:500}.k-calendar-day[aria-selected=date] .k-button{border-color:#a7bd68;color:#a7bd68}.k-calendar-today{text-align:center;padding-top:.5rem}.k-calendar-today .k-button{color:#81a2be;font-size:.75rem;padding:1rem}.k-calendar-today .k-button-text{opacity:1}.k-counter{font-size:.75rem;color:#16171a;font-weight:600}.k-counter[data-invalid]{-webkit-box-shadow:none;box-shadow:none;border:0;color:#c82829}.k-counter-rules{color:#777;font-weight:400}[dir=ltr] .k-counter-rules{padding-left:.5rem}[dir=rtl] .k-counter-rules{padding-right:.5rem}.k-form-submitter{display:none}.k-form-buttons[data-theme=changes]{background:#de935f}.k-form-buttons[data-theme=lock]{background:#d16464}.k-form-buttons[data-theme=unlock]{background:#81a2be}.k-form-buttons .k-view{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.k-form-button.k-button,.k-form-buttons .k-view{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-form-button.k-button{font-weight:500;white-space:nowrap;line-height:1;height:2.5rem;padding:0 1rem}.k-form-button:first-child{margin-left:-1rem}.k-form-button:last-child{margin-right:-1rem}.k-form-lock-info{display:-webkit-box;display:-ms-flexbox;display:flex;font-size:.875rem;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:1.5em;padding:.625rem 0;margin-right:3rem}.k-form-lock-info>.k-icon{margin-right:.5rem}.k-form-lock-buttons{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0}.k-form-lock-loader{-webkit-animation:Spin 4s linear infinite;animation:Spin 4s linear infinite}.k-form-lock-loader .k-icon-loader{display:-webkit-box;display:-ms-flexbox;display:flex}.k-form-indicator-icon{color:#de935f}.k-form-indicator-info{font-size:.875rem;font-weight:600;padding:.75rem 1rem .25rem;line-height:1.25em;width:15rem}.k-field-label{font-weight:600;display:block;padding:0 0 .75rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;line-height:1.25rem}.k-field-label abbr{text-decoration:none;color:#999;padding-left:.25rem}.k-field-header{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline}.k-field-options{position:absolute;top:calc(-.5rem - 1px)}[dir=ltr] .k-field-options{right:0}[dir=rtl] .k-field-options{left:0}.k-field-options.k-button-group .k-dropdown{height:auto}.k-field-options.k-button-group .k-field-options-button.k-button{padding:.75rem;display:-webkit-box;display:-ms-flexbox;display:flex}.k-field[data-disabled]{cursor:not-allowed}.k-field[data-disabled] *{pointer-events:none}.k-field[data-disabled] .k-text[data-theme=help] *{pointer-events:auto}.k-field:focus-within>.k-field-header>.k-field-counter{display:block}.k-field-help{padding-top:.5rem}.k-fieldset{border:0}.k-fieldset .k-grid{grid-row-gap:2.25rem}@media screen and (min-width:30em){.k-fieldset .k-grid{grid-column-gap:1.5rem}}.k-sections>.k-column[data-width="1/3"] .k-fieldset .k-grid,.k-sections>.k-column[data-width="1/4"] .k-fieldset .k-grid{grid-template-columns:repeat(1,1fr)}.k-sections>.k-column[data-width="1/3"] .k-fieldset .k-grid .k-column,.k-sections>.k-column[data-width="1/4"] .k-fieldset .k-grid .k-column{grid-column-start:auto}.k-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:1;border:0;outline:0;background:none}.k-input-element{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.k-input-icon{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:0}.k-input[data-disabled]{pointer-events:none}.k-input[data-theme=field]{line-height:1;border:1px solid #ccc;background:#fff}.k-input[data-theme=field]:focus-within{border:1px solid #4271ae;-webkit-box-shadow:rgba(66,113,174,.25) 0 0 0 2px;box-shadow:0 0 0 2px rgba(66,113,174,.25)}.k-input[data-theme=field][data-disabled]{background:#efefef}.k-input[data-theme=field] .k-input-icon{width:2.25rem}.k-input[data-theme=field] .k-input-after,.k-input[data-theme=field] .k-input-before,.k-input[data-theme=field] .k-input-icon{-ms-flex-item-align:stretch;align-self:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-negative:0;flex-shrink:0}.k-input[data-theme=field] .k-input-after,.k-input[data-theme=field] .k-input-before{padding:0 .5rem}.k-input[data-theme=field] .k-input-before{color:#777;padding-right:0}.k-input[data-theme=field] .k-input-after{color:#777;padding-left:0}.k-input[data-theme=field] .k-input-icon>.k-dropdown{width:100%;height:100%}.k-input[data-theme=field] .k-input-icon-button{width:100%;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-ms-flex-negative:0;flex-shrink:0}.k-input[data-theme=field] .k-number-input,.k-input[data-theme=field] .k-select-input,.k-input[data-theme=field] .k-text-input{padding:.5rem;line-height:1.25rem}.k-input[data-theme=field] .k-date-input .k-select-input,.k-input[data-theme=field] .k-time-input .k-select-input{padding-left:0;padding-right:0}[dir=ltr] .k-input[data-theme=field] .k-date-input .k-select-input:first-child,[dir=ltr] .k-input[data-theme=field] .k-time-input .k-select-input:first-child{padding-left:.5rem}[dir=rtl] .k-input[data-theme=field] .k-date-input .k-select-input:first-child,[dir=rtl] .k-input[data-theme=field] .k-time-input .k-select-input:first-child{padding-right:.5rem}.k-input[data-theme=field] .k-date-input .k-select-input:focus-within,.k-input[data-theme=field] .k-time-input .k-select-input:focus-within{color:#4271ae;font-weight:600}.k-input[data-theme=field] .k-time-input .k-time-input-meridiem{padding-left:.5rem}.k-input[data-theme=field][data-type=checkboxes] .k-checkboxes-input li,.k-input[data-theme=field][data-type=checkboxes] .k-radio-input li,.k-input[data-theme=field][data-type=radio] .k-checkboxes-input li,.k-input[data-theme=field][data-type=radio] .k-radio-input li{min-width:0;overflow-wrap:break-word}.k-input[data-theme=field][data-type=checkboxes] .k-input-before{border-right:1px solid #efefef}.k-input[data-theme=field][data-type=checkboxes] .k-input-element+.k-input-after,.k-input[data-theme=field][data-type=checkboxes] .k-input-element+.k-input-icon{border-left:1px solid #efefef}.k-input[data-theme=field][data-type=checkboxes] .k-input-element{overflow:hidden}.k-input[data-theme=field][data-type=checkboxes] .k-checkboxes-input{display:grid;grid-template-columns:1fr;margin-bottom:-1px;margin-right:-1px}@media screen and (min-width:65em){.k-input[data-theme=field][data-type=checkboxes] .k-checkboxes-input{grid-template-columns:repeat(var(--columns),1fr)}}.k-input[data-theme=field][data-type=checkboxes] .k-checkboxes-input li{border-right:1px solid #efefef;border-bottom:1px solid #efefef}.k-input[data-theme=field][data-type=checkboxes] .k-checkboxes-input label{display:block;line-height:1.25rem;padding:.5rem .5rem}.k-input[data-theme=field][data-type=checkboxes] .k-checkbox-input-icon{top:.625rem;left:.5rem;margin-top:0}.k-input[data-theme=field][data-type=radio] .k-input-before{border-right:1px solid #efefef}.k-input[data-theme=field][data-type=radio] .k-input-element+.k-input-after,.k-input[data-theme=field][data-type=radio] .k-input-element+.k-input-icon{border-left:1px solid #efefef}.k-input[data-theme=field][data-type=radio] .k-input-element{overflow:hidden}.k-input[data-theme=field][data-type=radio] .k-radio-input{display:grid;grid-template-columns:1fr;margin-bottom:-1px;margin-right:-1px}@media screen and (min-width:65em){.k-input[data-theme=field][data-type=radio] .k-radio-input{grid-template-columns:repeat(var(--columns),1fr)}}.k-input[data-theme=field][data-type=radio] .k-radio-input li{border-right:1px solid #efefef;border-bottom:1px solid #efefef}.k-input[data-theme=field][data-type=radio] .k-radio-input label{display:block;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;min-height:2.25rem;line-height:1.25rem;padding:.5rem .5rem}.k-input[data-theme=field][data-type=radio] .k-radio-input label:before{top:.625rem;left:.5rem;margin-top:-1px}.k-input[data-theme=field][data-type=radio] .k-radio-input .k-radio-input-info{display:block;font-size:.875rem;color:#777;line-height:1.25rem;padding-top:.125rem}.k-input[data-theme=field][data-type=radio] .k-radio-input .k-icon{width:2.25rem;height:2.25rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.k-input[data-theme=field][data-type=range] .k-range-input{padding:.5rem}.k-input[data-theme=field][data-type=select]{position:relative}.k-input[data-theme=field][data-type=select] .k-input-icon{position:absolute;top:0;bottom:0}[dir=ltr] .k-input[data-theme=field][data-type=select] .k-input-icon{right:0}[dir=rtl] .k-input[data-theme=field][data-type=select] .k-input-icon{left:0}.k-input[data-theme=field][data-type=tags] .k-tags-input{padding:.25rem .25rem 0 .25rem}.k-input[data-theme=field][data-type=tags] .k-tag{margin-right:.25rem;margin-bottom:.25rem;height:1.75rem;font-size:.875rem}.k-input[data-theme=field][data-type=tags] .k-tags-input input{font-size:.875rem;padding:0 .25rem;height:1.75rem;line-height:1;margin-bottom:.25rem}.k-input[data-theme=field][data-type=tags] .k-tags-input .k-dropdown-content{top:calc(100% + .5rem + 2px)}.k-input[data-theme=field][data-type=multiselect]{position:relative}.k-input[data-theme=field][data-type=multiselect] .k-multiselect-input{padding:.25rem 2rem 0 .25rem;min-height:2.25rem}.k-input[data-theme=field][data-type=multiselect] .k-tag{margin-right:.25rem;margin-bottom:.25rem;height:1.75rem;font-size:.875rem}.k-input[data-theme=field][data-type=multiselect] .k-input-icon{position:absolute;top:0;right:0;bottom:0;pointer-events:none}.k-input[data-theme=field][data-type=textarea] .k-textarea-input-native{padding:.25rem .5rem;line-height:1.5rem}.k-input[data-theme=field][data-type=toggle] .k-input-before{padding-right:.25rem}.k-input[data-theme=field][data-type=toggle] .k-toggle-input{padding-left:.5rem}.k-input[data-theme=field][data-type=toggle] .k-toggle-input-label{padding:0 .5rem 0 .75rem;line-height:2.25rem}.k-upload input{position:absolute;top:0}[dir=ltr] .k-upload input{left:-3000px}[dir=rtl] .k-upload input{right:-3000px}.k-upload .k-headline{margin-bottom:.75rem}.k-upload-error-list,.k-upload-list{line-height:1.5em;font-size:.875rem}.k-upload-list-filename{color:#777}.k-upload-error-list li{padding:.75rem;background:#fff;border-radius:1px}.k-upload-error-list li:not(:last-child){margin-bottom:2px}.k-upload-error-filename{color:#c82829;font-weight:600}.k-upload-error-message{color:#777}.k-checkbox-input{position:relative;cursor:pointer}.k-checkbox-input-native{position:absolute;-webkit-appearance:none;-moz-appearance:none;appearance:none;width:0;height:0;opacity:0}.k-checkbox-input-label{display:block;padding-left:1.75rem}.k-checkbox-input-icon{position:absolute;left:0;width:1rem;height:1rem;border:2px solid #999}.k-checkbox-input-icon svg{position:absolute;width:12px;height:12px;display:none}.k-checkbox-input-icon path{stroke:#fff}.k-checkbox-input-native:checked+.k-checkbox-input-icon{border-color:#16171a;background:#16171a}.k-checkbox-input-native:checked+.k-checkbox-input-icon svg{display:block}.k-checkbox-input-native:focus+.k-checkbox-input-icon{border-color:#4271ae}.k-checkbox-input-native:focus:checked+.k-checkbox-input-icon{background:#4271ae}.k-date-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-date-input-separator{padding:0 .125rem}.k-datetime-input{display:-webkit-box;display:-ms-flexbox;display:flex}.k-datetime-input .k-time-input{padding-left:.5rem}.k-text-input{width:100%;border:0;background:none;font:inherit;color:inherit}.k-text-input::-webkit-input-placeholder{color:#999}.k-text-input::-moz-placeholder{color:#999}.k-text-input:-ms-input-placeholder{color:#999}.k-text-input::-ms-input-placeholder{color:#999}.k-text-input::placeholder{color:#999}.k-text-input:focus{outline:0}.k-text-input:invalid{-webkit-box-shadow:none;box-shadow:none;outline:0}.k-multiselect-input{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;position:relative;font-size:.875rem;min-height:2.25rem;line-height:1}.k-multiselect-input .k-sortable-ghost{background:#4271ae}.k-multiselect-input .k-dropdown-content{width:100%}.k-multiselect-search{margin-top:0!important;color:#fff;background:#16171a;border-bottom:1px dashed hsla(0,0%,100%,.2)}.k-multiselect-search>.k-button-text{-webkit-box-flex:1;-ms-flex:1;flex:1}.k-multiselect-search input{width:100%;color:#fff;background:none;border:none;outline:none;padding:.25rem 0;font:inherit}.k-multiselect-options{position:relative;max-height:240px;overflow-y:scroll;padding:.5rem 0}.k-multiselect-option{position:relative}.k-multiselect-option.selected{color:#a7bd68}.k-multiselect-option.disabled:not(.selected) .k-icon{opacity:0}.k-multiselect-option b{color:#81a2be;font-weight:700}.k-multiselect-value{color:#999;margin-left:.25rem}.k-multiselect-value:before{content:" ("}.k-multiselect-value:after{content:")"}.k-multiselect-input[data-layout=list] .k-tag{width:100%;margin-right:0!important}.k-number-input{width:100%;border:0;background:none;font:inherit;color:inherit}.k-number-input::-webkit-input-placeholder{color:$color-light-grey}.k-number-input::-moz-placeholder{color:$color-light-grey}.k-number-input:-ms-input-placeholder{color:$color-light-grey}.k-number-input::-ms-input-placeholder{color:$color-light-grey}.k-number-input::placeholder{color:$color-light-grey}.k-number-input:focus{outline:0}.k-number-input:invalid{-webkit-box-shadow:none;box-shadow:none;outline:0}.k-radio-input li{position:relative;line-height:1.5rem;padding-left:1.75rem}.k-radio-input input{position:absolute;width:0;height:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;opacity:0}.k-radio-input label{cursor:pointer;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-radio-input label:before{position:absolute;top:.175em;left:0;content:"";width:1rem;height:1rem;border-radius:50%;border:2px solid #999;-webkit-box-shadow:#fff 0 0 0 2px inset;box-shadow:inset 0 0 0 2px #fff}.k-radio-input input:checked+label:before{border-color:#16171a;background:#16171a}.k-radio-input input:focus+label:before{border-color:#4271ae}.k-radio-input input:focus:checked+label:before{background:#4271ae}.k-radio-input-text{display:block}.k-range-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-range-input-native{--min:0;--max:100;--value:0;--range:calc(var(--max) - var(--min));--ratio:calc((var(--value) - var(--min))/var(--range));--position:calc(8px + var(--ratio)*(100% - 16px));-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:16px;background:transparent;font-size:.875rem;line-height:1}.k-range-input-native::-webkit-slider-thumb{-webkit-appearance:none;appearance:none}.k-range-input-native::-webkit-slider-runnable-track{border:none;border-radius:4px;width:100%;height:4px;background:#ccc;background:-webkit-gradient(linear,left top,left bottom,from(#16171a),to(#16171a)) 0/var(--position) 100% no-repeat #ccc;background:linear-gradient(#16171a,#16171a) 0/var(--position) 100% no-repeat #ccc}.k-range-input-native::-moz-range-track{border:none;border-radius:4px;width:100%;height:4px;background:#ccc}.k-range-input-native::-ms-track{border:none;border-radius:4px;width:100%;height:4px;background:#ccc}.k-range-input-native::-moz-range-progress{height:4px;background:#16171a}.k-range-input-native::-ms-fill-lower{height:4px;background:#16171a}.k-range-input-native::-webkit-slider-thumb{margin-top:-6px;-webkit-box-sizing:border-box;box-sizing:border-box;width:16px;height:16px;background:#efefef;border:4px solid #16171a;border-radius:50%;cursor:pointer}.k-range-input-native::-moz-range-thumb{box-sizing:border-box;width:16px;height:16px;background:#efefef;border:4px solid #16171a;border-radius:50%;cursor:pointer}.k-range-input-native::-ms-thumb{margin-top:0;box-sizing:border-box;width:16px;height:16px;background:#efefef;border:4px solid #16171a;border-radius:50%;cursor:pointer}.k-range-input-native::-ms-tooltip{display:none}.k-range-input-native:focus{outline:none}.k-range-input-native:focus::-webkit-slider-runnable-track{border:none;border-radius:4px;width:100%;height:4px;background:#ccc;background:-webkit-gradient(linear,left top,left bottom,from(#4271ae),to(#4271ae)) 0/var(--position) 100% no-repeat #ccc;background:linear-gradient(#4271ae,#4271ae) 0/var(--position) 100% no-repeat #ccc}.k-range-input-native:focus::-moz-range-progress{height:4px;background:#4271ae}.k-range-input-native:focus::-ms-fill-lower{height:4px;background:#4271ae}.k-range-input-native:focus::-webkit-slider-thumb{background:#efefef;border:4px solid #4271ae}.k-range-input-native:focus::-moz-range-thumb{background:#efefef;border:4px solid #4271ae}.k-range-input-native:focus::-ms-thumb{background:#efefef;border:4px solid #4271ae}.k-range-input-tooltip{position:relative;max-width:20%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#fff;font-size:.75rem;line-height:1;text-align:center;border-radius:1px;background:#16171a;margin-left:1rem;padding:0 .25rem;white-space:nowrap}.k-range-input-tooltip:after{position:absolute;top:50%;left:-5px;width:0;height:0;-webkit-transform:translateY(-50%);transform:translateY(-50%);border-top:5px solid transparent;border-right:5px solid #16171a;border-bottom:5px solid transparent;content:""}.k-range-input-tooltip>*{padding:4px}.k-select-input{position:relative;display:block;cursor:pointer;overflow:hidden}.k-select-input-native{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;width:100%;font:inherit;z-index:1;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}.k-select-input-native[disabled]{cursor:default}.k-select-input-native{font-weight:400}.k-tags-input{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.k-tags-input .k-sortable-ghost{background:#4271ae}.k-tags-input-element{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;min-width:0}.k-tags-input:focus-within .k-tags-input-element{-ms-flex-preferred-size:4rem;flex-basis:4rem}.k-tags-input-element input{font:inherit;border:0;width:100%;background:none}.k-tags-input-element input:focus{outline:0}.k-tags-input[data-layout=list] .k-tag{width:100%;margin-right:0!important}.k-textarea-input-wrapper{position:relative}.k-textarea-input-native{resize:none;border:0;width:100%;background:none;font:inherit;line-height:1.5em;color:inherit}.k-textarea-input-native::-webkit-input-placeholder{color:#999}.k-textarea-input-native::-moz-placeholder{color:#999}.k-textarea-input-native:-ms-input-placeholder{color:#999}.k-textarea-input-native::-ms-input-placeholder{color:#999}.k-textarea-input-native::placeholder{color:#999}.k-textarea-input-native:focus{outline:0}.k-textarea-input-native:invalid{-webkit-box-shadow:none;box-shadow:none;outline:0}.k-textarea-input-native[data-size=small]{min-height:7.5rem}.k-textarea-input-native[data-size=medium]{min-height:15rem}.k-textarea-input-native[data-size=large]{min-height:30rem}.k-textarea-input-native[data-size=huge]{min-height:45rem}.k-textarea-input-native[data-font=monospace]{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}.k-toolbar{margin-bottom:.25rem;color:#aaa}.k-textarea-input:focus-within .k-toolbar{position:-webkit-sticky;position:sticky;top:0;right:0;left:0;z-index:1;-webkit-box-shadow:rgba(0,0,0,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(0,0,0,.05);border-bottom:1px solid rgba(0,0,0,.1);color:#000}.k-time-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:1}.k-time-input-separator{padding:0 .125rem}.k-time-input-meridiem{padding-left:.5rem}.k-toggle-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-toggle-input-native{position:relative;height:16px;width:32px;border-radius:16px;border:2px solid #999;-webkit-box-shadow:inset 0 0 0 2px #fff,inset -16px 0 0 2px #fff;box-shadow:inset 0 0 0 2px #fff,inset -16px 0 0 2px #fff;background-color:#999;outline:0;-webkit-transition:all .1s ease-in-out;transition:all .1s ease-in-out;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;-ms-flex-negative:0;flex-shrink:0}.k-toggle-input-native:checked{border-color:#16171a;-webkit-box-shadow:inset 0 0 0 2px #fff,inset 16px 0 0 2px #fff;box-shadow:inset 0 0 0 2px #fff,inset 16px 0 0 2px #fff;background-color:#16171a}.k-toggle-input-native[disabled]{border-color:#ccc;-webkit-box-shadow:inset 0 0 0 2px #efefef,inset -16px 0 0 2px #efefef;box-shadow:inset 0 0 0 2px #efefef,inset -16px 0 0 2px #efefef;background-color:#ccc}.k-toggle-input-native[disabled]:checked{-webkit-box-shadow:inset 0 0 0 2px #efefef,inset 16px 0 0 2px #efefef;box-shadow:inset 0 0 0 2px #efefef,inset 16px 0 0 2px #efefef}.k-toggle-input-native:focus:checked{border:2px solid #4271ae;background-color:#4271ae}.k-toggle-input-native::-ms-check{opacity:0}.k-toggle-input-label{cursor:pointer;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.k-files-field[data-disabled] *{pointer-events:all!important}body{counter-reset:headline-counter}.k-headline-field{position:relative;padding-top:1.5rem}.k-headline-field[data-numbered]:before{counter-increment:headline-counter;content:counter(headline-counter,decimal-leading-zero);color:#4271ae;font-weight:400;padding-right:.25rem}.k-fieldset>.k-grid .k-column:first-child .k-headline-field{padding-top:0}.k-info-field .k-headline{padding-bottom:.75rem;line-height:1.25rem}.k-line-field{position:relative;border:0;height:3rem;width:auto}.k-line-field:after{position:absolute;content:"";top:50%;margin-top:-1px;left:0;right:0;height:1px;background:#ccc}.k-pages-field[data-disabled] *{pointer-events:all!important}.k-structure-table{table-layout:fixed;width:100%;background:#fff;font-size:.875rem;border-spacing:0;-webkit-box-shadow:rgba(22,23,26,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(22,23,26,.05)}.k-structure-table td,.k-structure-table th{border-bottom:1px solid #efefef;line-height:1.25em;overflow:hidden;text-overflow:ellipsis}[dir=ltr] .k-structure-table td,[dir=ltr] .k-structure-table th{border-right:1px solid #efefef}[dir=rtl] .k-structure-table td,[dir=rtl] .k-structure-table th{border-left:1px solid #efefef}.k-structure-table th{font-weight:400;color:#777;padding:0 .75rem;height:38px}[dir=ltr] .k-structure-table th{text-align:left}[dir=rtl] .k-structure-table th{text-align:right}.k-structure-table td:last-child,.k-structure-table th:last-child{width:38px}[dir=ltr] .k-structure-table td:last-child,[dir=ltr] .k-structure-table th:last-child{border-right:0}[dir=rtl] .k-structure-table td:last-child,[dir=rtl] .k-structure-table th:last-child{border-left:0}.k-structure-table tr:last-child td{border-bottom:0}.k-structure-table tbody tr:hover td{background:hsla(0,0%,93.7%,.25)}@media screen and (max-width:65em){.k-structure-table td,.k-structure-table th{display:none}.k-structure-table td:first-child,.k-structure-table td:last-child,.k-structure-table td:nth-child(2),.k-structure-table th:first-child,.k-structure-table th:last-child,.k-structure-table th:nth-child(2){display:table-cell}}.k-structure-table .k-structure-table-column[data-align=center]{text-align:center}[dir=ltr] .k-structure-table .k-structure-table-column[data-align=right]{text-align:right}[dir=rtl] .k-structure-table .k-structure-table-column[data-align=right]{text-align:left}.k-structure-table .k-structure-table-column[data-width="1/2"]{width:50%}.k-structure-table .k-structure-table-column[data-width="1/3"]{width:33.33%}.k-structure-table .k-structure-table-column[data-width="1/4"]{width:25%}.k-structure-table .k-structure-table-column[data-width="1/5"]{width:20%}.k-structure-table .k-structure-table-column[data-width="1/6"]{width:16.66%}.k-structure-table .k-structure-table-column[data-width="1/8"]{width:12.5%}.k-structure-table .k-structure-table-column[data-width="1/9"]{width:11.11%}.k-structure-table .k-structure-table-column[data-width="2/3"]{width:66.66%}.k-structure-table .k-structure-table-column[data-width="3/4"]{width:75%}.k-structure-table .k-structure-table-index{width:38px;text-align:center}.k-structure-table .k-structure-table-index-number{font-size:.75rem;color:#999;padding-top:.15rem}.k-structure-table .k-sort-handle{width:38px;height:38px;display:none}.k-structure-table[data-sortable] tr:hover .k-structure-table-index-number{display:none}.k-structure-table[data-sortable] tr:hover .k-sort-handle{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.k-structure-table .k-structure-table-option{width:38px;text-align:center}.k-structure-table .k-structure-table-option .k-button{width:38px;height:38px}.k-structure-table .k-structure-table-text{padding:0 .75rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.k-structure-table .k-sortable-ghost{background:#fff;-webkit-box-shadow:rgba(22,23,26,.25) 0 5px 10px;box-shadow:0 5px 10px rgba(22,23,26,.25);outline:2px solid #4271ae;margin-bottom:2px;cursor:-webkit-grabbing}.k-sortable-row-fallback{opacity:0!important}.k-structure-backdrop{position:absolute;top:0;right:0;bottom:0;left:0;z-index:2;height:100vh}.k-structure-form{position:relative;z-index:3;border-radius:1px;margin-bottom:1px;-webkit-box-shadow:rgba(22,23,26,.05) 0 0 0 3px;box-shadow:0 0 0 3px rgba(22,23,26,.05);border:1px solid #ccc;background:#efefef}.k-structure-form-fields{padding:1.5rem 1.5rem 2rem}.k-structure-form-buttons{border-top:1px solid #ccc;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.k-structure-form-buttons .k-pagination{display:none}@media screen and (min-width:65em){.k-structure-form-buttons .k-pagination{display:-webkit-box;display:-ms-flexbox;display:flex}}.k-structure-form-buttons .k-pagination>.k-button,.k-structure-form-buttons .k-pagination>span{padding:.875rem 1rem!important}.k-structure-form-cancel-button,.k-structure-form-submit-button{padding:.875rem 1.5rem;line-height:1rem;display:-webkit-box;display:-ms-flexbox;display:flex}.k-field-counter{display:none}.k-text-field:focus-within .k-field-counter{display:block}.k-users-field[data-disabled] *{pointer-events:all!important}.k-toolbar{background:#fff;border-bottom:1px solid #efefef;height:38px}.k-toolbar-wrapper{position:absolute;top:0;right:0;left:0;max-width:100%}.k-toolbar-buttons{display:-webkit-box;display:-ms-flexbox;display:flex}.k-toolbar-divider{width:1px;background:#efefef}.k-toolbar-button{width:36px;height:36px}.k-toolbar-button:hover{background:hsla(0,0%,93.7%,.5)}.k-files-field-preview{display:grid;grid-gap:.5rem;grid-template-columns:repeat(auto-fill,1.525rem);padding:0 .75rem}.k-files-field-preview li{line-height:0}.k-files-field-preview li .k-icon{height:100%}.k-url-field-preview{padding:0 .75rem}.k-url-field-preview a{color:#4271ae;text-decoration:underline;-webkit-transition:color .3s;transition:color .3s;overflow:hidden;white-space:nowrap;max-width:100%;text-overflow:ellipsis}.k-url-field-preview a:hover{color:#000}.k-pages-field-preview{padding:0 .25rem 0 .75rem;display:-webkit-box;display:-ms-flexbox;display:flex}.k-pages-field-preview li{line-height:0;margin-right:.5rem}.k-pages-field-preview .k-link{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;background:#efefef;-webkit-box-shadow:rgba(22,23,26,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(22,23,26,.05)}.k-pages-field-preview-image{width:1.525rem;height:1.525rem;color:#999!important}.k-pages-field-preview figcaption{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;line-height:1.5em;padding:0 .5rem;border:1px solid #ccc;border-left:0;border-radius:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.k-toggle-field-preview label{padding:0 .25rem 0 .75rem;display:-webkit-box;display:-ms-flexbox;display:flex;height:38px;cursor:pointer;overflow:hidden;white-space:nowrap}.k-toggle-field-preview .k-toggle-input-label{padding-left:.5rem}.k-users-field-preview{padding:0 .25rem 0 .75rem;display:-webkit-box;display:-ms-flexbox;display:flex}.k-users-field-preview li{line-height:0;margin-right:.5rem}.k-users-field-preview .k-link{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;background:#efefef;-webkit-box-shadow:rgba(22,23,26,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(22,23,26,.05)}.k-users-field-preview-avatar{width:1.525rem;height:1.525rem;color:#999!important}.k-users-field-preview-avatar.k-image{display:block}.k-users-field-preview figcaption{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;line-height:1.5em;padding:0 .5rem;border:1px solid #ccc;border-left:0;border-radius:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.k-bar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;line-height:1}.k-bar-slot{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.k-bar-slot[data-position=center]{text-align:center}[dir=ltr] .k-bar-slot[data-position=right]{text-align:right}[dir=rtl] .k-bar-slot[data-position=right]{text-align:left}.k-box{background:#d9d9d9;border-radius:1px;padding:.375rem .75rem;line-height:1.25rem;border-left:2px solid #999;padding:.5rem 1.5rem;word-wrap:break-word;font-size:.875rem}.k-box[data-theme=code]{background:#16171a;border:1px solid #000;color:#efefef;font-family:Input,Menlo,monospace;font-size:.875rem;line-height:1.5}.k-box[data-theme=button]{padding:0}.k-box[data-theme=button] .k-button{padding:0 .75rem;height:2.25rem;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:2rem;text-align:left}.k-box[data-theme=positive]{background:#dbe4c1;border:0;border-left:2px solid #a7bd68;padding:.5rem 1.5rem}.k-box[data-theme=negative]{background:#eec6c6;border:0;border-left:2px solid #d16464;padding:.5rem 1.5rem}.k-box[data-theme=notice]{background:#f4dac9;border:0;border-left:2px solid #de935f;padding:.5rem 1.5rem}.k-box[data-theme=info]{background:#d5e0e9;border:0;border-left:2px solid #81a2be;padding:.5rem 1.5rem}.k-box[data-theme=empty]{text-align:center;border-left:0;padding:3rem 1.5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background:#efefef;border-radius:1px;color:#777;border:1px dashed #ccc}.k-box[data-theme=empty] .k-icon{margin-bottom:.5rem;color:#999}.k-box[data-theme=empty] p{color:#777}.k-card{position:relative;border-radius:1px;-webkit-box-shadow:rgba(22,23,26,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(22,23,26,.05)}.k-card,.k-card a{min-width:0;background:#fff}.k-card:focus-within{-webkit-box-shadow:#4271ae 0 0 0 2px;box-shadow:0 0 0 2px #4271ae}.k-card a:focus{outline:0}.k-card .k-sort-handle{position:absolute;top:.75rem;width:2rem;height:2rem;border-radius:1px;background:#fff;opacity:0;color:#16171a;z-index:1;will-change:opacity;-webkit-transition:opacity .3s;transition:opacity .3s}[dir=ltr] .k-card .k-sort-handle{right:.75rem}[dir=rtl] .k-card .k-sort-handle{left:.75rem}.k-cards:hover .k-sort-handle{opacity:.25}.k-card:hover .k-sort-handle{opacity:1}.k-card.k-sortable-ghost{outline:2px solid #4271ae;border-radius:0}.k-card-icon,.k-card-image{border-top-left-radius:1px;border-top-right-radius:1px;overflow:hidden}.k-card-icon{position:relative;display:block}.k-card-icon .k-icon{position:absolute;top:0;right:0;bottom:0;left:0}.k-card-icon .k-icon-emoji{font-size:3rem}.k-card-icon .k-icon svg{width:3rem;height:3rem}.k-card-content{line-height:1.25rem;border-bottom-left-radius:1px;border-bottom-right-radius:1px;min-height:2.25rem;padding:.5rem .75rem;overflow-wrap:break-word;word-wrap:break-word}.k-card-text{display:block;font-weight:400;text-overflow:ellipsis;font-size:.875rem}.k-card-text[data-noinfo]:after{content:" ";height:1em;width:5rem;display:inline-block}.k-card-info{color:#777;display:block;font-size:.875rem;text-overflow:ellipsis;overflow:hidden}[dir=ltr] .k-card-info{margin-right:4rem}[dir=rtl] .k-card-info{margin-left:4rem}.k-card-options{position:absolute;bottom:0}[dir=ltr] .k-card-options{right:0}[dir=rtl] .k-card-options{left:0}.k-card-options>.k-button{position:relative;float:left;height:2.25rem;padding:0 .75rem;line-height:1}.k-card-options-dropdown{top:2.25rem}.k-cards{display:grid;grid-gap:1.5rem;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr))}@media screen and (min-width:30em){.k-cards[data-size=tiny]{grid-template-columns:repeat(auto-fill,minmax(12rem,1fr))}.k-cards[data-size=small]{grid-template-columns:repeat(auto-fill,minmax(16rem,1fr))}.k-cards[data-size=medium]{grid-template-columns:repeat(auto-fill,minmax(24rem,1fr))}.k-cards[data-size=huge],.k-cards[data-size=large]{grid-template-columns:1fr}}@media screen and (min-width:65em){.k-cards[data-size=large]{grid-template-columns:repeat(auto-fill,minmax(32rem,1fr))}}.k-collection-help{padding:.5rem .75rem}.k-collection-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin-right:-.75rem;margin-left:-.75rem}.k-collection-pagination{line-height:1.25rem;min-height:2.75rem}.k-collection-pagination .k-pagination .k-button{padding:.5rem .75rem;line-height:1.125rem}.k-column{min-width:0;grid-column-start:span 12}@media screen and (min-width:65em){.k-column[data-width="1/1"],.k-column[data-width="2/2"],.k-column[data-width="3/3"],.k-column[data-width="4/4"],.k-column[data-width="6/6"]{grid-column-start:span 12}.k-column[data-width="1/2"],.k-column[data-width="2/4"],.k-column[data-width="3/6"]{grid-column-start:span 6}.k-column[data-width="1/3"],.k-column[data-width="2/6"]{grid-column-start:span 4}.k-column[data-width="2/3"],.k-column[data-width="4/6"]{grid-column-start:span 8}.k-column[data-width="1/4"]{grid-column-start:span 3}.k-column[data-width="1/6"]{grid-column-start:span 2}.k-column[data-width="5/6"]{grid-column-start:span 10}.k-column[data-width="3/4"]{grid-column-start:span 9}}.k-dropzone{position:relative}.k-dropzone:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;display:none;pointer-events:none;z-index:1}.k-dropzone[data-over]:after{display:block;outline:1px solid #4271ae;-webkit-box-shadow:rgba(66,113,174,.25) 0 0 0 3px;box-shadow:0 0 0 3px rgba(66,113,174,.25)}.k-empty{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;border-radius:1px;color:#777;border:1px dashed #ccc}.k-empty p{font-size:.875rem;color:#777}.k-empty>.k-icon{color:#999}.k-empty[data-layout=cards]{text-align:center;padding:1.5rem;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.k-empty[data-layout=cards] .k-icon{margin-bottom:1rem}.k-empty[data-layout=cards] .k-icon svg{width:2rem;height:2rem}.k-empty[data-layout=list]{min-height:38px}.k-empty[data-layout=list]>.k-icon{width:36px;min-height:36px;border-right:1px solid rgba(0,0,0,.05)}.k-empty[data-layout=list]>p{line-height:1.25rem;padding:.5rem .75rem}.k-file-preview{background:#2d2f36}.k-file-preview-layout{display:grid}@media screen and (max-width:65em){.k-file-preview-layout{padding:0!important}}@media screen and (min-width:30em){.k-file-preview-layout{grid-template-columns:50% auto}}@media screen and (min-width:65em){.k-file-preview-layout{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}}.k-file-preview-layout>*{min-width:0}.k-file-preview-image{position:relative;background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXR0ZXJuIGlkPSJhIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiPjxwYXRoIGZpbGw9InJnYmEoMCwgMCwgMCwgMC4yKSIgZD0iTTAgMGgxMHYxMEgwem0xMCAxMGgxMHYxMEgxMHoiLz48L3BhdHRlcm4+PHJlY3QgZmlsbD0idXJsKCNhKSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIvPjwvc3ZnPg==")}@media screen and (min-width:65em){.k-file-preview-image{width:33.33%}}@media screen and (min-width:90em){.k-file-preview-image{width:25%}}.k-file-preview-image .k-image span{overflow:hidden;padding-bottom:66.66%}@media screen and (min-width:30em) and (max-width:65em){.k-file-preview-image .k-image span{position:absolute;top:0;left:0;bottom:0;right:0;padding-bottom:0!important}}@media screen and (min-width:65em){.k-file-preview-image .k-image span{padding-bottom:100%}}.k-file-preview-placeholder{display:block;padding-bottom:100%}.k-file-preview-image img{padding:3rem}.k-file-preview-image-link{display:block;outline:0}.k-file-preview-image-link.k-link[data-tabbed]{-webkit-box-shadow:none;box-shadow:none;outline:2px solid #4271ae;outline-offset:-2px}.k-file-preview-icon{position:relative;display:block;padding-bottom:100%;overflow:hidden;color:hsla(0,0%,100%,.5)}.k-file-preview-icon svg{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%) scale(4);transform:translate(-50%,-50%) scale(4)}.k-file-preview-details{padding:1.5rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}@media screen and (min-width:65em){.k-file-preview-details{padding:3rem}}.k-file-preview-details ul{line-height:1.5em;max-width:50rem;display:grid;grid-gap:1.5rem 3rem;grid-template-columns:repeat(auto-fill,minmax(100px,1fr))}@media screen and (min-width:30em){.k-file-preview-details ul{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}.k-file-preview-details h3{font-size:.875rem;font-weight:500;color:#999}.k-file-preview-details p{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:hsla(0,0%,100%,.75);font-size:.875rem}.k-file-preview-details p a{display:block;width:100%;overflow:hidden;text-overflow:ellipsis}.k-grid{--columns:12;display:grid;grid-column-gap:0;grid-row-gap:0;grid-template-columns:1fr}@media screen and (min-width:30em){.k-grid[data-gutter=small]{grid-column-gap:1rem;grid-row-gap:1rem}.k-grid[data-gutter=huge],.k-grid[data-gutter=large],.k-grid[data-gutter=medium]{grid-column-gap:1.5rem;grid-row-gap:1.5rem}}@media screen and (min-width:65em){.k-grid{grid-template-columns:repeat(var(--columns),1fr)}.k-grid[data-gutter=large]{grid-column-gap:3rem}.k-grid[data-gutter=huge]{grid-column-gap:4.5rem}}@media screen and (min-width:90em){.k-grid[data-gutter=large]{grid-column-gap:4.5rem}.k-grid[data-gutter=huge]{grid-column-gap:6rem}}@media screen and (min-width:120em){.k-grid[data-gutter=large]{grid-column-gap:6rem}.k-grid[data-gutter=huge]{grid-column-gap:7.5rem}}.k-header{border-bottom:1px solid #ccc;margin-bottom:2rem;padding-top:4vh}.k-header .k-headline{min-height:1.25em;margin-bottom:.5rem}.k-header .k-header-buttons{margin-top:-.5rem;height:3.25rem}.k-header .k-headline-editable{cursor:pointer}.k-header .k-headline-editable .k-icon{color:#999;opacity:0;-webkit-transition:opacity .3s;transition:opacity .3s;display:inline-block}[dir=ltr] .k-header .k-headline-editable .k-icon{margin-left:.5rem}[dir=rtl] .k-header .k-headline-editable .k-icon{margin-right:.5rem}.k-header .k-headline-editable:hover .k-icon{opacity:1}.k-header-tabs{position:relative;background:#e9e9e9;border-top:1px solid #ccc;border-left:1px solid #ccc;border-right:1px solid #ccc}.k-header-tabs nav{display:-webkit-box;display:-ms-flexbox;display:flex;margin-left:-1px;margin-right:-1px}.k-header-tabs nav,.k-tab-button.k-button{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.k-tab-button.k-button{position:relative;z-index:1;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:.625rem .75rem;font-size:.75rem;text-transform:uppercase;text-align:center;font-weight:500;border-left:1px solid transparent;border-right:1px solid #ccc;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-width:15rem}@media screen and (min-width:30em){.k-tab-button.k-button{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}}@media screen and (min-width:30em){.k-tab-button.k-button .k-icon{margin-right:.5rem}}.k-tab-button.k-button>.k-button-text{padding-top:.375rem;font-size:10px;overflow:hidden;max-width:10rem;text-overflow:ellipsis}[dir=ltr] .k-tab-button.k-button>.k-button-text{padding-left:0}[dir=rtl] .k-tab-button.k-button>.k-button-text{padding-right:0}@media screen and (min-width:30em){.k-tab-button.k-button>.k-button-text{font-size:.75rem;padding-top:0}}.k-tab-button:last-child{border-right:1px solid transparent}.k-tab-button[aria-current]{position:relative;background:#efefef;border-right:1px solid #ccc;pointer-events:none}.k-tab-button[aria-current]:first-child{border-left:1px solid #ccc}.k-tab-button[aria-current]:after,.k-tab-button[aria-current]:before{position:absolute;content:""}.k-tab-button[aria-current]:before{left:-1px;right:-1px;height:2px;top:-1px;background:#16171a}.k-tab-button[aria-current]:after{left:0;right:0;height:1px;bottom:-1px;background:#efefef}.k-tabs-dropdown{top:100%;right:0}.k-list .k-list-item:not(:last-child){margin-bottom:2px}.k-list-item{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#fff;border-radius:1px;-webkit-box-shadow:rgba(22,23,26,.05) 0 2px 5px;box-shadow:0 2px 5px rgba(22,23,26,.05)}.k-list-item .k-sort-handle{position:absolute;left:-1.5rem;width:1.5rem;height:38px;opacity:0}.k-list:hover .k-sort-handle{opacity:.25}.k-list-item:hover .k-sort-handle{opacity:1}.k-list-item.k-sortable-ghost{position:relative;outline:2px solid #4271ae;z-index:1;-webkit-box-shadow:rgba(22,23,26,.25) 0 5px 10px;box-shadow:0 5px 10px rgba(22,23,26,.25)}.k-list-item.k-sortable-fallback{opacity:.25!important;overflow:hidden}.k-list-item-image{width:38px;height:38px;overflow:hidden;-ms-flex-negative:0;flex-shrink:0;line-height:0}.k-list-item-image .k-image{width:38px;height:38px;-o-object-fit:contain;object-fit:contain}.k-list-item-image .k-icon{width:38px;height:38px}.k-list-item-image .k-icon svg{opacity:.5}.k-list-item-content{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1;overflow:hidden;outline:none}.k-list-item-content[data-tabbed]{outline:none;-webkit-box-shadow:#4271ae 0 0 0 2px,rgba(66,113,174,.2) 0 0 0 2px;box-shadow:0 0 0 2px #4271ae,0 0 0 2px rgba(66,113,174,.2)}.k-list-item-text{display:-webkit-box;display:-ms-flexbox;display:flex;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;width:100%;line-height:1.25rem;padding:.5rem .75rem}.k-list-item-text em{font-style:normal;margin-right:1rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:.875rem;color:#16171a}.k-list-item-text em,.k-list-item-text small{min-width:0;overflow:hidden;text-overflow:ellipsis}.k-list-item-text small{color:#999;font-size:.75rem;color:#777;display:none}@media screen and (min-width:30em){.k-list-item-text small{display:block}}.k-list-item-status{height:auto!important}.k-list-item-options{position:relative;-ms-flex-negative:0;flex-shrink:0}.k-list-item-options .k-dropdown-content{top:38px}.k-list-item-options>.k-button{height:38px;padding:0 12px}.k-list-item-options>.k-button>.k-button-icon{height:38px}.k-view{padding-left:1.5rem;padding-right:1.5rem;margin:0 auto;max-width:100rem}@media screen and (min-width:30em){.k-view{padding-left:3rem;padding-right:3rem}}@media screen and (min-width:90em){.k-view{padding-left:6rem;padding-right:6rem}}.k-view[data-align=center]{height:calc(100vh - 6rem);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:0 3rem;overflow:auto}.k-view[data-align=center]>*{-ms-flex-preferred-size:22.5rem;flex-basis:22.5rem}.k-headline{font-size:1rem;font-weight:600;line-height:1.5em}.k-headline[data-size=small]{font-size:.875rem}.k-headline[data-size=large]{font-size:1.25rem;font-weight:400}@media screen and (min-width:65em){.k-headline[data-size=large]{font-size:1.5rem}}.k-headline[data-size=huge]{font-size:1.5rem;line-height:1.15em}@media screen and (min-width:65em){.k-headline[data-size=huge]{font-size:1.75rem}}.k-headline[data-theme=negative]{color:#c82829}.k-headline[data-theme=positive]{color:#5d800d}.k-headline abbr{color:#999;padding-left:.25rem;text-decoration:none}.k-icon{position:relative;line-height:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-ms-flex-negative:0;flex-shrink:0}.k-icon svg{width:1rem;height:1rem;-moz-transform:scale(1)}.k-icon svg *{fill:currentColor}.k-icon[data-back=black]{background:#16171a;color:#fff}.k-icon[data-back=white]{background:#fff;color:#16171a}.k-icon[data-back=pattern]{background:#2d2f36 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXR0ZXJuIGlkPSJhIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiPjxwYXRoIGZpbGw9InJnYmEoMCwgMCwgMCwgMC4yKSIgZD0iTTAgMGgxMHYxMEgwem0xMCAxMGgxMHYxMEgxMHoiLz48L3BhdHRlcm4+PHJlY3QgZmlsbD0idXJsKCNhKSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIvPjwvc3ZnPg==");color:#fff}.k-icon[data-size=medium] svg{width:2rem;height:2rem}.k-icon[data-size=large] svg{width:3rem;height:3rem}.k-icon-emoji{display:block;line-height:1;font-style:normal;font-size:1rem}@media not all,only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.k-icon-emoji{font-size:1.25rem;margin-left:.2rem}}.k-image span{position:relative;display:block;line-height:0;padding-bottom:100%}.k-image img{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;-o-object-fit:contain;object-fit:contain}.k-image-error{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#fff;font-size:.9em}.k-image-error svg *{fill:hsla(0,0%,100%,.3)}.k-image[data-cover] img{-o-object-fit:cover;object-fit:cover}.k-image[data-back=black] span{background:#16171a}.k-image[data-back=white] span{background:#fff;color:#16171a}.k-image[data-back=white] .k-image-error{background:#16171a;color:#fff}.k-image[data-back=pattern] span{background:#2d2f36 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXR0ZXJuIGlkPSJhIiB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiPjxwYXRoIGZpbGw9InJnYmEoMCwgMCwgMCwgMC4yKSIgZD0iTTAgMGgxMHYxMEgwem0xMCAxMGgxMHYxMEgxMHoiLz48L3BhdHRlcm4+PHJlY3QgZmlsbD0idXJsKCNhKSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIvPjwvc3ZnPg==")}.k-progress{-webkit-appearance:none;width:100%;height:.5rem;border-radius:5rem}.k-progress::-webkit-progress-bar{border:none;background:#ccc;height:.5rem;border-radius:20px}.k-progress::-webkit-progress-value{border-radius:20px;background:#4271ae;-webkit-transition:width .3s;transition:width .3s}.k-sort-handle{cursor:-webkit-grab;color:#16171a;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:0;width:2rem;height:2rem;display:-webkit-box;display:-ms-flexbox;display:flex;will-change:opacity,color;-webkit-transition:opacity .3s;transition:opacity .3s;z-index:1}.k-sort-handle svg{width:1rem}.k-sort-handle:active{cursor:-webkit-grabbing}.k-text{line-height:1.5em}.k-text p{margin-bottom:1.5em}.k-text a{text-decoration:underline}.k-text>:last-child{margin-bottom:0}.k-text[data-align=center]{text-align:center}.k-text[data-align=right]{text-align:right}.k-text[data-size=tiny]{font-size:.75rem}.k-text[data-size=small]{font-size:.875rem}.k-text[data-size=medium]{font-size:1rem}.k-text[data-size=large]{font-size:1.25rem}.k-text[data-theme=help]{font-size:.875rem;color:#777;line-height:1.25rem}button{line-height:inherit;border:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;font-size:1rem;color:currentColor;background:none;cursor:pointer}button::-moz-focus-inner{padding:0;border:0}.k-button{display:inline-block;position:relative;font-size:.875rem;-webkit-transition:color .3s;transition:color .3s}.k-button,.k-button:focus,.k-button:hover{outline:none}.k-button[data-tabbed]{outline:none;-webkit-box-shadow:#4271ae 0 0 0 2px,rgba(66,113,174,.2) 0 0 0 2px;box-shadow:0 0 0 2px #4271ae,0 0 0 2px rgba(66,113,174,.2)}.k-button *{vertical-align:middle}.k-button[data-responsive] .k-button-text{display:none}@media screen and (min-width:30em){.k-button[data-responsive] .k-button-text{display:inline}}.k-button[data-theme=positive]{color:#5d800d}.k-button[data-theme=negative]{color:#c82829}.k-button-icon{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:0}[dir=ltr] .k-button-icon~.k-button-text{padding-left:.5rem}[dir=rtl] .k-button-icon~.k-button-text{padding-right:.5rem}.k-button-text{opacity:.75}.k-button:focus .k-button-text,.k-button:hover .k-button-text{opacity:1}.k-button-text b,.k-button-text span{vertical-align:baseline}.k-button[data-disabled]{opacity:.5;cursor:default}.k-button[data-disabled]:focus .k-button-text,.k-button[data-disabled]:hover .k-button-text{opacity:.75}.k-button-group{font-size:0;margin-left:-.75rem;margin-right:-.75rem}.k-button-group>.k-dropdown{height:3rem;display:inline-block}.k-button-group>.k-button,.k-button-group>.k-dropdown>.k-button{padding:1rem .75rem;line-height:1rem}.k-button-group .k-dropdown-content{top:calc(100% + 1px);margin:0 .75rem}.k-dropdown{position:relative}.k-dropdown-content{position:absolute;top:100%;background:#16171a;color:#fff;z-index:700;-webkit-box-shadow:rgba(22,23,26,.2) 0 2px 10px;box-shadow:0 2px 10px rgba(22,23,26,.2);border-radius:1px;text-align:left;margin-bottom:6rem}[dir=ltr] .k-dropdown-content{left:0}[dir=rtl] .k-dropdown-content{right:0}[dir=ltr] .k-dropdown-content[data-align=right]{left:auto;right:0}[dir=rtl] .k-dropdown-content[data-align=right]{left:0;right:auto}.k-dropdown-content>.k-dropdown-item:first-child{margin-top:.5rem}.k-dropdown-content>.k-dropdown-item:last-child{margin-bottom:.5rem}.k-dropdown-content hr{position:relative;padding:.5rem 0;border:0}.k-dropdown-content hr:after{position:absolute;top:.5rem;left:1rem;right:1rem;content:"";height:1px;background:currentColor;opacity:.2}.k-dropdown-item{white-space:nowrap;line-height:1;display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:.875rem;padding:6px 16px}.k-dropdown-item:focus{outline:none;-webkit-box-shadow:#4271ae 0 0 0 2px,rgba(66,113,174,.2) 0 0 0 2px;box-shadow:0 0 0 2px #4271ae,0 0 0 2px rgba(66,113,174,.2)}.k-dropdown-item .k-button-figure{text-align:center;padding-right:.5rem}.k-link{outline:none}.k-link[data-tabbed]{outline:none;-webkit-box-shadow:#4271ae 0 0 0 2px,rgba(66,113,174,.2) 0 0 0 2px;box-shadow:0 0 0 2px #4271ae,0 0 0 2px rgba(66,113,174,.2)}.k-pagination{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;direction:ltr}.k-pagination .k-button{padding:1rem}.k-pagination-details{white-space:nowrap}.k-pagination>span{font-size:.875rem}.k-pagination[data-align=center]{text-align:center}.k-pagination[data-align=right]{text-align:right}.k-dropdown-content.k-pagination-selector{position:absolute;top:100%;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);background:#000}[dir=ltr] .k-dropdown-content.k-pagination-selector{direction:ltr}[dir=rtl] .k-dropdown-content.k-pagination-selector{direction:rtl}.k-pagination-settings{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.k-pagination-settings .k-button{line-height:1}.k-pagination-settings label{display:-webkit-box;display:-ms-flexbox;display:flex;border-right:1px solid hsla(0,0%,100%,.35);-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:.625rem 1rem;font-size:.75rem}.k-pagination-settings label span{margin-right:.5rem}.k-prev-next{direction:ltr}.k-search{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;overflow:auto;background:rgba(22,23,26,.6)}.k-search-box{max-width:30rem;margin:0 auto;-webkit-box-shadow:rgba(22,23,26,.2) 0 2px 10px;box-shadow:0 2px 10px rgba(22,23,26,.2)}@media screen and (min-width:65em){.k-search-box{margin:2.5rem auto}}.k-search-input{background:#efefef}.k-search-input,.k-search-types{display:-webkit-box;display:-ms-flexbox;display:flex}.k-search-types{-ms-flex-negative:0;flex-shrink:0}.k-search-types>.k-button{padding:0 0 0 .7rem;font-size:1rem;line-height:1;height:2.5rem}.k-search-types>.k-button .k-icon{height:2.5rem}.k-search-types>.k-button .k-button-text{opacity:1;font-weight:500}.k-search-input input{background:none;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font:inherit;padding:.75rem;border:0;height:2.5rem}.k-search-close{width:2.5rem;line-height:1}.k-search input:focus{outline:0}.k-search ul{background:#fff}.k-search li{border-bottom:1px solid #efefef;line-height:1.125;display:-webkit-box;display:-ms-flexbox;display:flex}.k-search li .k-link{display:block;padding:.5rem .75rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.k-search li strong{display:block;font-size:.875rem;font-weight:400}.k-search li small{font-size:.75rem;color:#777}.k-search li[data-selected]{outline:2px solid #4271ae;background:rgba(66,113,174,.25);border-bottom:1px solid transparent}.k-search-empty{padding:.825rem .75rem;font-size:.75rem;background:#efefef;border-top:1px dashed #ccc;color:#777}.k-tag{position:relative;font-size:.875rem;line-height:1;cursor:pointer;background-color:#16171a;color:#efefef;border-radius:1px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.k-tag:focus{outline:0;background-color:#4271ae;border-color:#4271ae;color:#fff}.k-tag-text{padding:0 .75rem}.k-tag-toggle{color:hsla(0,0%,100%,.7);width:2rem;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-left:1px solid hsla(0,0%,100%,.15)}.k-tag-toggle:hover{background:hsla(0,0%,100%,.2);color:#fff}.k-topbar{position:relative;color:#fff;-ms-flex-negative:0;flex-shrink:0;height:2.5rem;line-height:1;background:#16171a}.k-topbar-wrapper{position:relative;margin-left:-.75rem;margin-right:-.75rem}.k-topbar-loader,.k-topbar-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-topbar-loader{position:absolute;top:0;right:0;bottom:0;height:2.5rem;width:2.5rem;padding:.75rem;background:#16171a;z-index:1;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.k-topbar-loader svg{height:18px;width:18px;-webkit-animation:Spin .9s linear infinite;animation:Spin .9s linear infinite}.k-topbar-menu{-ms-flex-negative:0;flex-shrink:0}.k-topbar-menu ul{padding:.5rem 0}.k-topbar-menu-button{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-topbar-menu-button .k-button-text{opacity:1}.k-topbar-button,.k-topbar-signals-button{padding:.75rem;line-height:1;font-size:.875rem}.k-topbar-signals .k-button .k-button-text{opacity:1}.k-topbar-button .k-button-text{display:-webkit-box;display:-ms-flexbox;display:flex;opacity:1}.k-topbar-view-button{-ms-flex-negative:0;flex-shrink:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}[dir=ltr] .k-topbar-view-button{padding-right:0}[dir=rtl] .k-topbar-view-button{padding-left:0}[dir=ltr] .k-topbar-view-button .k-icon{margin-right:.5rem}[dir=rtl] .k-topbar-view-button .k-icon{margin-left:.5rem}.k-topbar-crumbs{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-ms-flexbox;display:flex}.k-topbar-crumbs a{position:relative;font-size:.875rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:none;padding-top:.75rem;padding-bottom:.75rem;line-height:1;-webkit-transition:opacity .3s;transition:opacity .3s;outline:none}.k-topbar-crumbs a:before{content:"/";padding:0 .5rem;opacity:.25}.k-topbar-crumbs a:focus,.k-topbar-crumbs a:hover{opacity:1}.k-topbar-crumbs a[data-tabbed]{outline:none;-webkit-box-shadow:#4271ae 0 0 0 2px,rgba(66,113,174,.2) 0 0 0 2px;box-shadow:0 0 0 2px #4271ae,0 0 0 2px rgba(66,113,174,.2)}.k-topbar-crumbs a:not(:last-child){max-width:15vw}.k-topbar-breadcrumb-menu{-ms-flex-negative:0;flex-shrink:0}@media screen and (min-width:30em){.k-topbar-crumbs a{display:block}.k-topbar-breadcrumb-menu{display:none}}.k-topbar-signals{position:absolute;top:0;background:#16171a;height:2.5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}[dir=ltr] .k-topbar-signals{right:0}[dir=rtl] .k-topbar-signals{left:0}.k-topbar-signals:before{position:absolute;content:"";top:0;bottom:0;width:.5rem}[dir=ltr] .k-topbar-signals:before{left:-.5rem;background:-webkit-linear-gradient(left,rgba(22,23,26,0),#16171a)}[dir=rtl] .k-topbar-signals:before{right:-.5rem;background:-webkit-linear-gradient(right,rgba(22,23,26,0),#16171a)}.k-topbar-signals .k-button{line-height:1}.k-topbar-notification{font-weight:600;line-height:1;display:-webkit-box;display:-ms-flexbox;display:flex}.k-topbar .k-button[data-theme=positive]{color:#a7bd68}.k-topbar .k-button[data-theme=negative]{color:#d16464}.k-topbar .k-button[data-theme=negative] .k-button-text{display:none}@media screen and (min-width:30em){.k-topbar .k-button[data-theme=negative] .k-button-text{display:inline}}.k-topbar .k-button[data-theme] .k-button-text{opacity:1}.k-topbar .k-dropdown-content{color:#16171a;background:#fff}.k-topbar .k-dropdown-content hr:after{opacity:.1}.k-topbar-menu [aria-current] .k-link{color:#4271ae;font-weight:500}.k-registration{display:inline-block;margin-right:1rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.k-registration p{color:#d16464;font-size:.875rem;margin-right:1rem;font-weight:600;display:none}@media screen and (min-width:90em){.k-registration p{display:block}}.k-registration .k-button{color:#fff}.k-section,.k-sections{padding-bottom:3rem}.k-section-header{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;z-index:1}.k-section-header .k-headline{line-height:1.25rem;padding-bottom:.75rem;min-height:2rem}.k-section-header .k-button-group{position:absolute;top:-.875rem}[dir=ltr] .k-section-header .k-button-group{right:0}[dir=rtl] .k-section-header .k-button-group{left:0}.k-fields-issue-headline,.k-info-section-headline{margin-bottom:.5rem}.k-fields-section input[type=submit]{display:none}[data-locked] .k-fields-section{opacity:.2;pointer-events:none}.k-browser-view .k-error-view-content{text-align:left}.k-error-view{position:absolute;top:0;right:0;bottom:0;left:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.k-error-view-content{line-height:1.5em;max-width:25rem;text-align:center}.k-error-view-icon{color:#c82829;display:inline-block}.k-error-view-content p:not(:last-child){margin-bottom:.75rem}.k-installation-view .k-button{display:block;margin-top:1.5rem}.k-installation-view .k-headline{margin-bottom:.75rem}.k-installation-issues{line-height:1.5em;font-size:.875rem}.k-installation-issues li{position:relative;padding:1.5rem;background:#fff}[dir=ltr] .k-installation-issues li{padding-left:3.5rem}[dir=rtl] .k-installation-issues li{padding-right:3.5rem}.k-installation-issues .k-icon{position:absolute;top:calc(1.5rem + 2px)}[dir=ltr] .k-installation-issues .k-icon{left:1.5rem}[dir=rtl] .k-installation-issues .k-icon{right:1.5rem}.k-installation-issues .k-icon svg *{fill:#c82829}.k-installation-issues li:not(:last-child){margin-bottom:2px}.k-installation-issues li code{font:inherit;color:#c82829}.k-installation-view .k-button[type=submit]{padding:1rem}[dir=ltr] .k-installation-view .k-button[type=submit]{margin-left:-1rem}[dir=rtl] .k-installation-view .k-button[type=submit]{margin-right:-1rem}.k-login-form label abbr{visibility:hidden}.k-login-buttons{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:1.5rem 0}.k-login-button{padding:.5rem 1rem;font-weight:500;-webkit-transition:opacity .3s;transition:opacity .3s}[dir=ltr] .k-login-button{margin-right:-1rem}[dir=rtl] .k-login-button{margin-left:-1rem}.k-login-button span{opacity:1}.k-login-button[disabled]{opacity:.25}.k-login-checkbox{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:.5rem 0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:.875rem;cursor:pointer}.k-login-checkbox .k-checkbox-text{opacity:.75;-webkit-transition:opacity .3s;transition:opacity .3s}.k-login-checkbox:focus span,.k-login-checkbox:hover span{opacity:1}.k-login-alert{padding:.5rem .75rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;min-height:38px;margin-bottom:2rem;background:#c82829;color:#fff;font-size:.875rem;border-radius:1px;-webkit-box-shadow:rgba(22,23,26,.2) 0 2px 10px;box-shadow:0 2px 10px rgba(22,23,26,.2);cursor:pointer}.k-status-flag svg{width:14px;height:14px}.k-status-flag-listed .k-icon{color:#a7bd68}.k-status-flag-unlisted .k-icon{color:#81a2be}.k-status-flag-draft .k-icon{color:#d16464}.k-status-flag[disabled]{opacity:1}.k-settings-view section{margin-bottom:3rem}.k-settings-view .k-header{margin-bottom:1.5rem}.k-settings-view header{margin-bottom:.5rem;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.k-settings-view header,.k-system-info-box{display:-webkit-box;display:-ms-flexbox;display:flex}.k-system-info-box{background:#fff;padding:.75rem}.k-system-info-box li{-ms-flex-negative:0;flex-shrink:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0}.k-system-info-box dt{font-size:.875rem;color:#777;margin-bottom:.25rem}.k-system-unregistered{color:#c82829}.k-languages-section{margin-bottom:2rem}.k-user-profile{background:#fff}.k-user-profile>.k-view{padding-top:3rem;padding-bottom:3rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;line-height:0}.k-user-profile .k-button-group{overflow:hidden}[dir=ltr] .k-user-profile .k-button-group{margin-left:.75rem}[dir=rtl] .k-user-profile .k-button-group{margin-right:.75rem}.k-user-profile .k-button-group .k-button{display:block;padding-top:.25rem;padding-bottom:.25rem;overflow:hidden;white-space:nowrap}.k-user-profile .k-button-group .k-button[disabled]{opacity:1}.k-user-profile .k-dropdown-content{margin-top:.5rem;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.k-user-view-image .k-image{display:block;width:4rem;height:4rem;line-height:0}.k-user-view-image .k-button-text{opacity:1}.k-user-view-image .k-icon{width:4rem;height:4rem;background:#16171a;color:#999}.k-user-name-placeholder{color:#999;-webkit-transition:color .3s;transition:color .3s}.k-header[data-editable] .k-user-name-placeholder:hover{color:#16171a}
\ No newline at end of file
diff --git a/panel/dist/img/icons.svg b/panel/dist/img/icons.svg
index 87ef6686c5..090d7abb23 100644
--- a/panel/dist/img/icons.svg
+++ b/panel/dist/img/icons.svg
@@ -30,12 +30,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -44,10 +64,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -65,6 +115,10 @@
+
+
+
+
@@ -159,6 +213,9 @@
+
+
+
@@ -168,6 +225,13 @@
+
+
+
+
+
+
+
@@ -186,6 +250,14 @@
+
+
+
+
+
+
+
+
@@ -198,13 +270,13 @@
-
-
-
+
+
+
@@ -219,6 +291,9 @@
+
+
+
@@ -229,18 +304,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -248,9 +339,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -272,9 +375,16 @@
+
+
+
+
+
+
+
@@ -292,49 +402,23 @@
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/panel/dist/js/app.js b/panel/dist/js/app.js
index 3a080c213f..ac43618e20 100644
--- a/panel/dist/js/app.js
+++ b/panel/dist/js/app.js
@@ -1 +1 @@
-(function(t){function e(e){for(var i,o,r=e[0],l=e[1],u=e[2],d=0,p=[];d1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",i="-";return n="a-z0-9"+n,t=t.trim().toLowerCase(),e.forEach(function(e){e&&nt()(e).forEach(function(n){var i="/"!==n.substr(0,1),s=n.substring(1,n.length-1),a=i?n:s;t=t.replace(new RegExp(RegExp.escape(a),"g"),e[n])})}),t=t.replace("/[^\t\n\r -~]/",""),t=t.replace(new RegExp("[^"+n+"]","ig"),i),t=t.replace(new RegExp("["+RegExp.escape(i)+"]{2,}","g"),i),t=t.replace("/",i),t=t.replace(new RegExp("^[^"+n+"]+","g"),""),t=t.replace(new RegExp("[^"+n+"]+$","g"),""),t},pt={mixins:[h],data:function(){return{parent:null,file:{id:null,name:null,filename:null,extension:null}}},computed:{fields:function(){return{name:{label:this.$t("name"),type:"text",required:!0,icon:"title",after:"."+this.file.extension,preselect:!0}}},slugs:function(){return this.$store.state.languages.default?this.$store.state.languages.default.rules:this.system.slugs},system:function(){return this.$store.state.system.info}},methods:{open:function(t,e){var n=this;this.$api.files.get(t,e,{select:["id","filename","name","extension"]}).then(function(e){n.file=e,n.parent=t,n.$refs.dialog.open()}).catch(function(t){n.$store.dispatch("notification/error",t)})},sluggify:function(t){return dt(t,[this.slugs,this.system.ascii],".")},submit:function(){var t=this;this.file.name=this.file.name.trim(),0!==this.file.name.length?this.$api.files.rename(this.parent,this.file.filename,this.file.name).then(function(e){t.$store.dispatch("form/move",{old:t.$store.getters["form/id"](t.file.id),new:t.$store.getters["form/id"](e.id)}),t.$store.dispatch("notification/success",":)"),t.$emit("success",e),t.$events.$emit("file.changeName",e),t.$refs.dialog.close()}).catch(function(e){t.$refs.dialog.error(e.message)}):this.$refs.dialog.error(this.$t("error.file.changeName.empty"))}}},ft=pt,ht=Object(u["a"])(ft,Q,tt,!1,null,null,null),mt=ht.exports,gt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",staticClass:"k-files-dialog",attrs:{size:"medium"},on:{cancel:function(e){return t.$emit("cancel")},submit:t.submit}},[t.issue?[n("k-box",{attrs:{text:t.issue,theme:"negative"}})]:[t.models.length?n("k-list",t._l(t.models,function(e){return n("k-list-item",{key:e.filename,attrs:{text:e.text,info:e.info,image:e.image,icon:e.icon},on:{click:function(n){return t.toggle(e)}}},[t.isSelected(e)?n("k-button",{attrs:{slot:"options",autofocus:!0,icon:t.checkedIcon,tooltip:t.$t("remove"),theme:"positive"},slot:"options"}):n("k-button",{attrs:{slot:"options",autofocus:!0,tooltip:t.$t("select"),icon:"circle-outline"},slot:"options"})],1)}),1):n("k-empty",{attrs:{icon:"image"}},[t._v("\n "+t._s(t.$t("dialog.files.empty"))+"\n ")])]],2)},bt=[],vt=n("db0c"),kt=n.n(vt),$t=n("a745"),_t=n.n($t),yt={data:function(){return{models:[],issue:null,selected:{},options:{endpoint:null,max:null,multiple:!0,parent:null,selected:[]}}},computed:{multiple:function(){return!0===this.options.multiple&&1!==this.options.max},checkedIcon:function(){return!0===this.multiple?"check":"circle-filled"}},methods:{fetch:function(){var t=this;return this.$api.get(this.options.endpoint,this.fetchData||{}).then(function(e){t.models=e.data||e.pages||e,t.onFetched&&t.onFetched(e)}).catch(function(e){t.models=[],t.issue=e.message})},open:function(t,e){var n=this,i=!0;_t()(t)?(this.models=t,i=!1):(this.models=[],e=t),this.options=Object(k["a"])({},this.options,e),this.selected={},this.options.selected.forEach(function(t){n.$set(n.selected,t,{id:t})}),i?this.fetch().then(function(){n.$refs.dialog.open()}):this.$refs.dialog.open()},submit:function(){this.$emit("submit",kt()(this.selected)),this.$refs.dialog.close()},isSelected:function(t){return void 0!==this.selected[t.id]},toggle:function(t){!1!==this.options.multiple&&1!==this.options.max||(this.selected={}),!0!==this.isSelected(t)?this.options.max&&this.options.max<=nt()(this.selected).length||this.$set(this.selected,t.id,t):this.$delete(this.selected,t.id)}}},wt={mixins:[yt]},xt=wt,Ot=(n("bf53"),Object(u["a"])(xt,gt,bt,!1,null,null,null)),Ct=Ot.exports,St=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("language.create"),notification:t.notification,theme:"positive",size:"medium"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields,novalidate:!0},on:{submit:t.submit},model:{value:t.language,callback:function(e){t.language=e},expression:"language"}})],1)},Et=[],jt={mixins:[h],data:function(){return{notification:null,language:{name:"",code:"",direction:"ltr",locale:""}}},computed:{fields:function(){return{name:{label:this.$t("language.name"),type:"text",required:!0,icon:"title"},code:{label:this.$t("language.code"),type:"text",required:!0,counter:!1,icon:"globe",width:"1/2"},direction:{label:this.$t("language.direction"),type:"select",required:!0,empty:!1,options:[{value:"ltr",text:this.$t("language.direction.ltr")},{value:"rtl",text:this.$t("language.direction.rtl")}],width:"1/2"},locale:{label:this.$t("language.locale"),type:"text",placeholder:"en_US"}}},system:function(){return this.$store.state.system.info}},watch:{"language.name":function(t){this.onNameChanges(t)},"language.code":function(t){this.language.code=dt(t,[this.system.ascii])}},methods:{onNameChanges:function(t){this.language.code=dt(t,[this.language.rules,this.system.ascii]).substr(0,2)},open:function(){this.language={name:"",code:"",direction:"ltr"},this.$refs.dialog.open()},submit:function(){var t=this;this.$api.post("languages",{name:this.language.name,code:this.language.code,direction:this.language.direction,locale:this.language.locale}).then(function(){t.$store.dispatch("languages/load"),t.success({message:":)",event:"language.create"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},Tt=jt,Lt=Object(u["a"])(Tt,St,Et,!1,null,null,null),It=Lt.exports,qt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("delete"),theme:"negative",icon:"trash"},on:{submit:t.submit}},[n("k-text",{domProps:{innerHTML:t._s(t.$t("language.delete.confirm",{name:t.language.name}))}})],1)},At=[],Nt={mixins:[h],data:function(){return{language:{name:null}}},methods:{open:function(t){var e=this;this.$api.get("languages/"+t).then(function(t){e.language=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.delete("languages/"+this.language.code).then(function(){t.$store.dispatch("languages/load"),t.success({message:t.$t("language.deleted"),event:"language.delete"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},Bt=Nt,Pt=Object(u["a"])(Bt,qt,At,!1,null,null,null),Dt=Pt.exports,Mt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("save"),notification:t.notification,size:"medium"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.language,callback:function(e){t.language=e},expression:"language"}})],1)},Rt=[],zt=n("7618"),Ft={mixins:[It],computed:{fields:function(){var t=It.computed.fields.apply(this);return t.code.disabled=!0,"object"===Object(zt["a"])(this.language.locale)&&(t.locale={label:t.locale.label,type:"info",text:this.$t("language.locale.warning")}),t}},methods:{onNameChanges:function(){return!1},open:function(t){var e=this;this.$api.get("languages/"+t).then(function(t){e.language=t;var n=nt()(e.language.locale);1===n.length&&(e.language.locale=e.language.locale[n[0]]),e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.patch("languages/"+this.language.code,{name:this.language.name,direction:this.language.direction,locale:this.language.locale}).then(function(){t.$store.dispatch("languages/load"),t.success({message:t.$t("language.updated"),event:"language.update"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},Ut=Ft,Ht=Object(u["a"])(Ut,Mt,Rt,!1,null,null,null),Kt=Ht.exports,Vt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("page.draft.create"),notification:t.notification,size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()},close:t.reset}},[n("k-form",{ref:"form",attrs:{fields:t.fields,novalidate:!0},on:{submit:t.submit},model:{value:t.page,callback:function(e){t.page=e},expression:"page"}})],1)},Yt=[],Wt=(n("b54a"),{mixins:[h],data:function(){return{notification:null,parent:null,section:null,templates:[],page:this.emptyForm()}},computed:{fields:function(){return{title:{label:this.$t("title"),type:"text",required:!0,icon:"title"},slug:{label:this.$t("slug"),type:"text",required:!0,counter:!1,icon:"url"},template:{name:"template",label:this.$t("template"),type:"select",disabled:1===this.templates.length,required:!0,icon:"code",empty:!1,options:this.templates}}},slugs:function(){return this.$store.state.languages.default?this.$store.state.languages.default.rules:this.system.slugs},system:function(){return this.$store.state.system.info}},watch:{"page.title":function(t){this.page.slug=dt(t,[this.slugs,this.system.ascii])}},methods:{emptyForm:function(){return{title:"",slug:"",template:null}},open:function(t,e,n){var i=this;this.parent=t,this.section=n,this.$api.get(e,{section:n}).then(function(t){i.templates=t.map(function(t){return{value:t.name,text:t.title}}),i.templates[0]&&(i.page.template=i.templates[0].value),i.$refs.dialog.open()}).catch(function(t){i.$store.dispatch("notification/error",t)})},submit:function(){var t=this;if(this.page.title=this.page.title.trim(),0===this.page.title.length)return this.$refs.dialog.error("Please enter a title"),!1;var e={template:this.page.template,slug:this.page.slug,content:{title:this.page.title}};this.$api.post(this.parent+"/children",e).then(function(e){t.success({route:t.$api.pages.link(e.id),message:":)",event:"page.create"})}).catch(function(e){t.$refs.dialog.error(e.message)})},reset:function(){this.page=this.emptyForm()}}}),Gt=Wt,Jt=Object(u["a"])(Gt,Vt,Yt,!1,null,null,null),Zt=Jt.exports,Xt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("duplicate"),notification:t.notification,size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields,novalidate:!0},on:{submit:t.submit},model:{value:t.page,callback:function(e){t.page=e},expression:"page"}})],1)},Qt=[],te={mixins:[h],data:function(){return{notification:null,page:{children:!1,files:!1,hasChildren:!1,hasDrafts:!1,hasFiles:!1,id:null,slug:""}}},computed:{fields:function(){var t=this.page.hasChildren||this.page.hasDrafts,e=this.page.hasFiles,n={slug:{label:this.$t("slug"),type:"text",required:!0,counter:!1,spellcheck:!1,icon:"url"}};return e&&(n.files={label:this.$t("page.duplicate.files"),type:"toggle",required:!0,width:t?"1/2":null}),t&&(n.children={label:this.$t("page.duplicate.pages"),type:"toggle",required:!0,width:e?"1/2":null}),n},slugs:function(){return this.$store.state.languages.default?this.$store.state.languages.default.rules:this.system.slugs},system:function(){return this.$store.state.system.info}},watch:{"page.slug":function(t){this.page.slug=dt(t,[this.slugs,this.system.ascii])}},methods:{open:function(t){var e=this;this.$api.pages.get(t,{language:"@default",select:"id,slug,hasChildren,hasDrafts,hasFiles,title"}).then(function(t){e.page.id=t.id,e.page.slug=t.slug+"-"+dt(e.$t("page.duplicate.appendix")),e.page.hasChildren=t.hasChildren,e.page.hasDrafts=t.hasDrafts,e.page.hasFiles=t.hasFiles,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.pages.duplicate(this.page.id,this.page.slug,{children:this.page.children,files:this.page.files}).then(function(e){t.success({route:t.$api.pages.link(e.id),message:":)",event:"page.duplicate"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},ee=te,ne=Object(u["a"])(ee,Xt,Qt,!1,null,null,null),ie=ne.exports,se=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("delete"),size:t.hasSubpages?"medium":"small",theme:"negative",icon:"trash"},on:{submit:t.submit,close:t.reset}},[t.page.hasChildren||t.page.hasDrafts?[n("k-text",{domProps:{innerHTML:t._s(t.$t("page.delete.confirm",{title:t.page.title}))}}),n("div",{staticClass:"k-page-remove-warning"},[n("k-box",{attrs:{theme:"negative"},domProps:{innerHTML:t._s(t.$t("page.delete.confirm.subpages"))}})],1),t.hasSubpages?n("k-form",{attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.model,callback:function(e){t.model=e},expression:"model"}}):t._e()]:[n("k-text",{domProps:{innerHTML:t._s(t.$t("page.delete.confirm",{title:t.page.title}))},on:{keydown:function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:t.submit(e)}}})]],2)},ae=[],oe={mixins:[h],data:function(){return{page:{title:null,hasChildren:!1,hasDrafts:!1},model:this.emptyForm()}},computed:{hasSubpages:function(){return this.page.hasChildren||this.page.hasDrafts},fields:function(){return{check:{label:this.$t("page.delete.confirm.title"),type:"text",counter:!1}}}},methods:{emptyForm:function(){return{check:null}},open:function(t){var e=this;this.$api.pages.get(t,{select:"id, title, hasChildren, hasDrafts, parent"}).then(function(t){e.page=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.hasSubpages&&this.model.check!==this.page.title?this.$refs.dialog.error(this.$t("error.page.delete.confirm")):this.$api.pages.delete(this.page.id,{force:!0}).then(function(){t.$store.dispatch("form/remove","pages/"+t.page.id);var e={message:":)",event:"page.delete"};t.$route.params.path&&t.page.id===t.$route.params.path.replace(/\+/g,"/")&&(t.page.parent?e.route=t.$api.pages.link(t.page.parent.id):e.route="/pages"),t.success(e)}).catch(function(e){t.$refs.dialog.error(e.message)})},reset:function(){this.model=this.emptyForm()}}},re=oe,le=(n("12fb"),Object(u["a"])(re,se,ae,!1,null,null,null)),ue=le.exports,ce=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("rename"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.page,callback:function(e){t.page=e},expression:"page"}})],1)},de=[],pe={mixins:[h],data:function(){return{page:{id:null,title:null}}},computed:{fields:function(){return{title:{label:this.$t("title"),type:"text",required:!0,icon:"title",preselect:!0}}}},methods:{open:function(t){var e=this;this.$api.pages.get(t,{select:["id","title"]}).then(function(t){e.page=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.page.title=this.page.title.trim(),0!==this.page.title.length?this.$api.pages.title(this.page.id,this.page.title).then(function(){t.success({message:":)",event:"page.changeTitle"})}).catch(function(e){t.$refs.dialog.error(e.message)}):this.$refs.dialog.error(this.$t("error.page.changeTitle.empty"))}}},fe=pe,he=Object(u["a"])(fe,ce,de,!1,null,null,null),me=he.exports,ge=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),size:"medium",theme:"positive"},on:{submit:t.submit}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.changeStatus},model:{value:t.form,callback:function(e){t.form=e},expression:"form"}})],1)},be=[],ve={mixins:[h],data:function(){return{page:{id:null},isBlocked:!1,isIncomplete:!1,form:{status:null,position:null},states:{}}},computed:{fields:function(){var t=this,e={status:{name:"status",label:this.$t("page.changeStatus.select"),type:"radio",required:!0,options:nt()(this.states).map(function(e){return{value:e,text:t.states[e].label,info:t.states[e].text}})}};return"listed"===this.form.status&&"default"===this.page.blueprint.num&&(e.position={name:"position",label:this.$t("page.changeStatus.position"),type:"select",empty:!1,options:this.sortingOptions()}),e}},methods:{sortingOptions:function(){var t=this,e=[],n=0;return this.page.siblings.forEach(function(i){if(i.id===t.page.id||i.num<1)return!1;n++,e.push({value:n,text:n}),e.push({value:i.id,text:i.title,disabled:!0})}),e.push({value:n+1,text:n+1}),e},open:function(t){var e=this;this.$api.pages.get(t,{select:["id","status","num","errors","siblings","blueprint"]}).then(function(t){return!1===t.blueprint.options.changeStatus?e.$store.dispatch("notification/error",{message:e.$t("error.page.changeStatus.permission")}):"draft"===t.status&&nt()(t.errors).length>0?e.$store.dispatch("notification/error",{message:e.$t("error.page.changeStatus.incomplete"),details:t.errors}):(e.states=t.blueprint.status,e.page=t,e.form.status=t.status,e.form.position=t.num||t.siblings.length+1,void e.$refs.dialog.open())}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){this.$refs.form.submit()},changeStatus:function(){var t=this;this.$api.pages.status(this.page.id,this.form.status,this.form.position||1).then(function(){t.success({message:":)",event:"page.changeStatus"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},ke=ve,$e=Object(u["a"])(ke,ge,be,!1,null,null,null),_e=$e.exports,ye=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.page,callback:function(e){t.page=e},expression:"page"}})],1)},we=[],xe={mixins:[h],data:function(){return{blueprints:[],page:{id:null,template:null}}},computed:{fields:function(){return{template:{label:this.$t("template"),type:"select",required:!0,empty:!1,options:this.page.blueprints,icon:"template"}}}},methods:{open:function(t){var e=this;this.$api.pages.get(t,{select:["id","template","blueprints"]}).then(function(t){if(t.blueprints.length<=1)return e.$store.dispatch("notification/error",{message:e.$t("error.page.changeTemplate.invalid",{slug:t.id})});e.page=t,e.page.blueprints=e.page.blueprints.map(function(t){return{text:t.title,value:t.name}}),e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$events.$emit("keydown.cmd.s"),this.$api.pages.template(this.page.id,this.page.template).then(function(){t.success({message:":)",event:"page.changeTemplate"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},Oe=xe,Ce=Object(u["a"])(Oe,ye,we,!1,null,null,null),Se=Ce.exports,Ee=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",on:{submit:t.submit}},[n("k-text-field",t._b({attrs:{value:t.slug},on:{input:function(e){return t.sluggify(e)}}},"k-text-field",t.field,!1),[n("k-button",{attrs:{slot:"options",icon:"wand","data-options":""},on:{click:function(e){return t.sluggify(t.page.title)}},slot:"options"},[t._v("\n "+t._s(t.$t("page.changeSlug.fromTitle"))+"\n ")])],1)],1)],1)},je=[],Te={mixins:[h],data:function(){return{slug:null,url:null,page:{id:null,parent:null,title:null}}},computed:{field:function(){return{name:"slug",label:this.$t("slug"),type:"text",required:!0,icon:"url",help:"/"+this.url,counter:!1,preselect:!0}},slugs:function(){return this.$store.state.languages.current?this.$store.state.languages.current.rules:this.system.slugs},system:function(){return this.$store.state.system.info}},methods:{sluggify:function(t){this.slug=dt(t,[this.slugs,this.system.ascii]),this.page.parents?this.url=this.page.parents.map(function(t){return t.slug}).concat([this.slug]).join("/"):this.url=this.slug},open:function(t){var e=this;this.$api.pages.get(t,{view:"panel"}).then(function(t){e.page=t,e.sluggify(e.page.slug),e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;if(this.slug===this.page.slug)return this.$refs.dialog.close(),void this.$store.dispatch("notification/success",":)");0!==this.slug.length?this.$api.pages.slug(this.page.id,this.slug).then(function(e){t.$store.dispatch("form/move",{old:t.$store.getters["form/id"](t.page.id),new:t.$store.getters["form/id"](e.id)});var n={message:":)",event:"page.changeSlug"};!t.$route.params.path||t.page.id!==t.$route.params.path.replace(/\+/g,"/")||t.$store.state.languages.current&&!0!==t.$store.state.languages.current.default||(n.route=t.$api.pages.link(e.id),delete n.event),t.success(n)}).catch(function(e){t.$refs.dialog.error(e.message)}):this.$refs.dialog.error(this.$t("error.page.slug.invalid"))}}},Le=Te,Ie=Object(u["a"])(Le,Ee,je,!1,null,null,null),qe=Ie.exports,Ae=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",staticClass:"k-pages-dialog",attrs:{size:"medium"},on:{cancel:function(e){return t.$emit("cancel")},submit:t.submit}},[t.issue?[n("k-box",{attrs:{text:t.issue,theme:"negative"}})]:[t.model?n("header",{staticClass:"k-pages-dialog-navbar"},[n("k-button",{attrs:{disabled:!t.model.id,tooltip:t.$t("back"),icon:"angle-left"},on:{click:t.back}}),n("k-headline",[t._v(t._s(t.model.title))])],1):t._e(),t.models.length?n("k-list",t._l(t.models,function(e){return n("k-list-item",{key:e.id,attrs:{text:e.text,info:e.info,image:e.image,icon:e.icon},on:{click:function(n){return t.toggle(e)}}},[n("template",{slot:"options"},[t.isSelected(e)?n("k-button",{attrs:{slot:"options",autofocus:!0,icon:t.checkedIcon,tooltip:t.$t("remove"),theme:"positive"},slot:"options"}):n("k-button",{attrs:{slot:"options",autofocus:!0,tooltip:t.$t("select"),icon:"circle-outline"},slot:"options"}),t.model?n("k-button",{attrs:{disabled:!e.hasChildren,tooltip:t.$t("open"),icon:"angle-right"},on:{click:function(n){return n.stopPropagation(),t.go(e)}}}):t._e()],1)],2)}),1):n("k-empty",{attrs:{icon:"page"}},[t._v("\n "+t._s(t.$t("dialog.pages.empty"))+"\n ")])]],2)},Ne=[],Be={mixins:[yt],data:function(){var t=yt.data();return Object(k["a"])({},t,{model:{title:null,parent:null},options:Object(k["a"])({},t.options,{parent:null})})},computed:{fetchData:function(){return{parent:this.options.parent}}},methods:{back:function(){this.options.parent=this.model.parent,this.fetch()},go:function(t){this.options.parent=t.id,this.fetch()},onFetched:function(t){this.model=t.model}}},Pe=Be,De=(n("ac27"),Object(u["a"])(Pe,Ae,Ne,!1,null,null,null)),Me=De.exports,Re={extends:me,methods:{open:function(){var t=this;this.$api.site.get({select:["title"]}).then(function(e){t.page=e,t.$refs.dialog.open()}).catch(function(e){t.$store.dispatch("notification/error",e)})},submit:function(){var t=this;this.$api.site.title(this.page.title).then(function(){t.$store.dispatch("system/title",t.page.title),t.success({message:":)",event:"site.changeTitle"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},ze=Re,Fe=Object(u["a"])(ze,it,st,!1,null,null,null),Ue=Fe.exports,He=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("create"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()},close:t.reset}},[n("k-form",{ref:"form",attrs:{fields:t.fields,novalidate:!0},on:{submit:t.create},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}})],1)},Ke=[],Ve=n("795b"),Ye=n.n(Ve),We=(n("5df3"),{mixins:[h],data:function(){return{user:this.emptyForm(),languages:[],roles:[]}},computed:{fields:function(){return{name:{label:this.$t("name"),type:"text",icon:"user"},email:{label:this.$t("email"),type:"email",icon:"email",link:!1,required:!0},password:{label:this.$t("password"),type:"password",icon:"key"},language:{label:this.$t("language"),type:"select",icon:"globe",options:this.languages,required:!0,empty:!1},role:{label:this.$t("role"),type:1===this.roles.length?"hidden":"radio",required:!0,options:this.roles}}}},methods:{create:function(){var t=this;this.$api.users.create(this.user).then(function(){t.success({message:":)",event:"user.create"})}).catch(function(e){t.$refs.dialog.error(e.message)})},emptyForm:function(){return{name:"",email:"",password:"",language:this.$store.state.system.info.defaultLanguage||"en",role:this.$user.role.name}},open:function(){var t=this,e=this.$api.roles.options({canBe:"created"}).then(function(e){t.roles=e,"admin"!==t.$user.role.name&&(t.roles=t.roles.filter(function(t){return"admin"!==t.value}))}).catch(function(e){t.$store.dispatch("notification/error",e)}),n=this.$api.translations.options().then(function(e){t.languages=e}).catch(function(e){t.$store.dispatch("notification/error",e)});Ye.a.all([e,n]).then(function(){t.$refs.dialog.open()})},reset:function(){this.user=this.emptyForm()}}}),Ge=We,Je=Object(u["a"])(Ge,He,Ke,!1,null,null,null),Ze=Je.exports,Xe=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}})],1)},Qe=[],tn={mixins:[h],data:function(){return{user:{id:null,email:null}}},computed:{fields:function(){return{email:{label:this.$t("email"),preselect:!0,required:!0,type:"email"}}}},methods:{open:function(t){var e=this;this.$api.users.get(t,{select:["id","email"]}).then(function(t){e.user=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.users.changeEmail(this.user.id,this.user.email).then(function(e){t.$store.dispatch("form/revert","users/"+t.user.id),t.$user.id===t.user.id&&t.$store.dispatch("user/email",t.user.email);var n={message:":)",event:"user.changeEmail"};"User"===t.$route.name&&(n.route=t.$api.users.link(e.id)),t.success(n)}).catch(function(e){t.$refs.dialog.error(e.message)})}}},en=tn,nn=Object(u["a"])(en,Xe,Qe,!1,null,null,null),sn=nn.exports,an=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),theme:"positive",icon:"check"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}})],1)},on=[],rn={mixins:[h],data:function(){return{user:{language:"en"},languages:[]}},computed:{fields:function(){return{language:{label:this.$t("language"),type:"select",icon:"globe",options:this.languages,required:!0,empty:!1}}}},created:function(){var t=this;this.$api.translations.options().then(function(e){t.languages=e})},methods:{open:function(t){var e=this;this.$api.users.get(t,{view:"compact"}).then(function(t){e.user=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.users.changeLanguage(this.user.id,this.user.language).then(function(e){t.user=e,t.$user.id===t.user.id&&t.$store.dispatch("user/language",t.user.language),t.success({message:":)",event:"user.changeLanguage"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},ln=rn,un=Object(u["a"])(ln,an,on,!1,null,null,null),cn=un.exports,dn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),theme:"positive",icon:"check"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.values,callback:function(e){t.values=e},expression:"values"}})],1)},pn=[],fn={mixins:[h],data:function(){return{user:null,values:{password:null,passwordConfirmation:null}}},computed:{fields:function(){return{password:{label:this.$t("user.changePassword.new"),type:"password",icon:"key"},passwordConfirmation:{label:this.$t("user.changePassword.new.confirm"),icon:"key",type:"password"}}}},methods:{open:function(t){var e=this;this.$api.users.get(t).then(function(t){e.user=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;return this.values.password.length<8?(this.$refs.dialog.error(this.$t("error.user.password.invalid")),!1):this.values.password!==this.values.passwordConfirmation?(this.$refs.dialog.error(this.$t("error.user.password.notSame")),!1):void this.$api.users.changePassword(this.user.id,this.values.password).then(function(){t.success({message:":)",event:"user.changePassword"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},hn=fn,mn=Object(u["a"])(hn,dn,pn,!1,null,null,null),gn=mn.exports,bn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("delete"),theme:"negative",icon:"trash"},on:{submit:t.submit}},[n("k-text",{domProps:{innerHTML:t._s(t.$t("user.delete.confirm",{email:t.user.email}))}})],1)},vn=[],kn={mixins:[h],data:function(){return{user:{email:null}}},methods:{open:function(t){var e=this;this.$api.users.get(t).then(function(t){e.user=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.users.delete(this.user.id).then(function(){t.$store.dispatch("form/remove","users/"+t.user.id),t.success({message:":)",event:"user.delete"}),"User"===t.$route.name&&t.$router.push("/users")}).catch(function(e){t.$refs.dialog.error(e.message)})}}},$n=kn,_n=Object(u["a"])($n,bn,vn,!1,null,null,null),yn=_n.exports,wn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("rename"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}})],1)},xn=[],On={mixins:[h],data:function(){return{user:{id:null,name:null}}},computed:{fields:function(){return{name:{label:this.$t("name"),type:"text",icon:"user",preselect:!0}}}},methods:{open:function(t){var e=this;this.$api.users.get(t,{select:["id","name"]}).then(function(t){e.user=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.user.name=this.user.name.trim(),this.$api.users.changeName(this.user.id,this.user.name).then(function(){t.$user.id===t.user.id&&t.$store.dispatch("user/name",t.user.name),t.success({message:":)",event:"user.changeName"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},Cn=On,Sn=Object(u["a"])(Cn,wn,xn,!1,null,null,null),En=Sn.exports,jn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("user.changeRole"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}})],1)},Tn=[],Ln={mixins:[h],data:function(){return{roles:[],user:{id:null,role:"visitor"}}},computed:{fields:function(){return{role:{label:this.$t("user.changeRole.select"),type:"radio",required:!0,options:this.roles}}}},methods:{open:function(t){var e=this;this.id=t,this.$api.users.get(t).then(function(t){e.$api.roles.options({canBe:"changed"}).then(function(n){e.roles=n,"admin"!==e.$user.role.name&&(e.roles=e.roles.filter(function(t){return"admin"!==t.value})),e.user=t,e.user.role=e.user.role.name,e.$refs.dialog.open()})}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.users.changeRole(this.user.id,this.user.role).then(function(){t.$user.id===t.user.id&&t.$store.dispatch("user/load"),t.success({message:":)",event:"user.changeRole"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},In=Ln,qn=Object(u["a"])(In,jn,Tn,!1,null,null,null),An=qn.exports,Nn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",staticClass:"k-users-dialog",attrs:{size:"medium"},on:{cancel:function(e){return t.$emit("cancel")},submit:t.submit}},[t.issue?[n("k-box",{attrs:{text:t.issue,theme:"negative"}})]:[t.models.length?n("k-list",t._l(t.models,function(e){return n("k-list-item",{key:e.email,attrs:{text:e.username,image:e.image,icon:e.icon},on:{click:function(n){return t.toggle(e)}}},[t.isSelected(e)?n("k-button",{attrs:{slot:"options",autofocus:!0,icon:t.checkedIcon,tooltip:t.$t("remove"),theme:"positive"},slot:"options"}):n("k-button",{attrs:{slot:"options",autofocus:!0,tooltip:t.$t("select"),icon:"circle-outline"},slot:"options"})],1)}),1):n("k-empty",{attrs:{icon:"users"}},[t._v("\n "+t._s(t.$t("dialog.users.empty"))+"\n ")])]],2)},Bn=[],Pn={mixins:[yt]},Dn=Pn,Mn=(n("7568"),Object(u["a"])(Dn,Nn,Bn,!1,null,null,null)),Rn=Mn.exports,zn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dropdown",{staticClass:"k-autocomplete"},[t._t("default"),n("k-dropdown-content",t._g({ref:"dropdown",attrs:{autofocus:!0}},t.$listeners),t._l(t.matches,function(e,i){return n("k-dropdown-item",t._b({key:i,on:{mousedown:function(n){return t.onSelect(e)},keydown:[function(n){return!n.type.indexOf("key")&&t._k(n.keyCode,"tab",9,n.key,"Tab")?null:(n.preventDefault(),t.onSelect(e))},function(n){return!n.type.indexOf("key")&&t._k(n.keyCode,"enter",13,n.key,"Enter")?null:(n.preventDefault(),t.onSelect(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"left",37,e.key,["Left","ArrowLeft"])?null:"button"in e&&0!==e.button?null:(e.preventDefault(),t.close(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"backspace",void 0,e.key,void 0)?null:(e.preventDefault(),t.close(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"delete",[8,46],e.key,["Backspace","Delete","Del"])?null:(e.preventDefault(),t.close(e))}]}},"k-dropdown-item",e,!1),[t._v("\n "+t._s(e.text)+"\n ")])}),1),t._v("\n "+t._s(t.query)+"\n")],2)},Fn=[],Un=(n("4917"),{props:{limit:10,skip:{type:Array,default:function(){return[]}},options:Array,query:String},data:function(){return{matches:[],selected:{text:null}}},methods:{close:function(){this.$refs.dropdown.close()},onSelect:function(t){this.$refs.dropdown.close(),this.$emit("select",t)},search:function(t){var e=this;if(!(t.length<1)){var n=new RegExp(RegExp.escape(t),"ig");this.matches=this.options.filter(function(t){return!!t.text&&(-1===e.skip.indexOf(t.value)&&null!==t.text.match(n))}).slice(0,this.limit),this.$emit("search",t,this.matches),this.$refs.dropdown.open()}}}}),Hn=Un,Kn=Object(u["a"])(Hn,zn,Fn,!1,null,null,null),Vn=Kn.exports,Yn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-calendar-input"},[n("nav",[n("k-button",{attrs:{icon:"angle-left"},on:{click:t.prev}}),n("span",{staticClass:"k-calendar-selects"},[n("k-select-input",{attrs:{options:t.months,disabled:t.disabled,required:!0},model:{value:t.month,callback:function(e){t.month=t._n(e)},expression:"month"}}),n("k-select-input",{attrs:{options:t.years,disabled:t.disabled,required:!0},model:{value:t.year,callback:function(e){t.year=t._n(e)},expression:"year"}})],1),n("k-button",{attrs:{icon:"angle-right"},on:{click:t.next}})],1),n("table",{staticClass:"k-calendar-table"},[n("thead",[n("tr",t._l(t.weekdays,function(e){return n("th",{key:"weekday_"+e},[t._v(t._s(e))])}),0)]),n("tbody",t._l(t.numberOfWeeks,function(e){return n("tr",{key:"week_"+e},t._l(t.days(e),function(e,i){return n("td",{key:"day_"+i,staticClass:"k-calendar-day",attrs:{"aria-current":!!t.isToday(e)&&"date","aria-selected":!!t.isCurrent(e)&&"date"}},[e?n("k-button",{on:{click:function(n){return t.select(e)}}},[t._v(t._s(e))]):t._e()],1)}),0)}),0),n("tfoot",[n("tr",[n("td",{staticClass:"k-calendar-today",attrs:{colspan:"7"}},[n("k-button",{on:{click:t.selectToday}},[t._v(t._s(t.$t("today")))])],1)])])])])},Wn=[],Gn=n("5a0c"),Jn=n.n(Gn),Zn=function(t,e){t=String(t);var n="";e=(e||2)-t.length;while(n.length0?t:7},weekdays:function(){return[this.$t("days.mon"),this.$t("days.tue"),this.$t("days.wed"),this.$t("days.thu"),this.$t("days.fri"),this.$t("days.sat"),this.$t("days.sun")]},monthnames:function(){return[this.$t("months.january"),this.$t("months.february"),this.$t("months.march"),this.$t("months.april"),this.$t("months.may"),this.$t("months.june"),this.$t("months.july"),this.$t("months.august"),this.$t("months.september"),this.$t("months.october"),this.$t("months.november"),this.$t("months.december")]},months:function(){var t=[];return this.monthnames.forEach(function(e,n){t.push({value:n,text:e})}),t},years:function(){for(var t=[],e=this.year-10;e<=this.year+10;e++)t.push({value:e,text:Zn(e)});return t}},watch:{value:function(t){var e=Jn()(t);this.day=e.date(),this.month=e.month(),this.year=e.year(),this.current=e}},methods:{days:function(t){for(var e=[],n=7*(t-1)+1,i=n;ithis.numberOfDays?e.push(""):e.push(s)}return e},next:function(){var t=this.date.clone().add(1,"month");this.set(t)},isToday:function(t){return this.month===this.today.month()&&this.year===this.today.year()&&t===this.today.date()},isCurrent:function(t){return this.month===this.current.month()&&this.year===this.current.year()&&t===this.current.date()},prev:function(){var t=this.date.clone().subtract(1,"month");this.set(t)},go:function(t,e){"today"===t&&(t=this.today.year(),e=this.today.month()),this.year=t,this.month=e},set:function(t){this.day=t.date(),this.month=t.month(),this.year=t.year()},selectToday:function(){this.set(Jn()()),this.select(this.day)},select:function(t){t&&(this.day=t);var e=Jn()(new Date(this.year,this.month,this.day,this.current.hour(),this.current.minute()));this.$emit("input",e.toISOString())}}},Qn=Xn,ti=(n("ee15"),Object(u["a"])(Qn,Yn,Wn,!1,null,null,null)),ei=ti.exports,ni=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{staticClass:"k-counter",attrs:{"data-invalid":!t.valid}},[n("span",[t._v(t._s(t.count))]),t.min&&t.max?n("span",{staticClass:"k-counter-rules"},[t._v("("+t._s(t.min)+"–"+t._s(t.max)+")")]):t.min?n("span",{staticClass:"k-counter-rules"},[t._v("≥ "+t._s(t.min))]):t.max?n("span",{staticClass:"k-counter-rules"},[t._v("≤ "+t._s(t.max))]):t._e()])},ii=[],si=(n("c5f6"),{props:{count:Number,min:Number,max:Number,required:{type:Boolean,default:!1}},computed:{valid:function(){return!1===this.required&&0===this.count||(!0!==this.required||0!==this.count)&&(!(this.min&&this.countthis.max))}}}),ai=si,oi=(n("fc0f"),Object(u["a"])(ai,ni,ii,!1,null,null,null)),ri=oi.exports,li=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("form",{ref:"form",staticClass:"k-form",attrs:{method:"POST",autocomplete:"off",novalidate:""},on:{submit:function(e){return e.preventDefault(),t.onSubmit(e)}}},[t._t("header"),t._t("default",[n("k-fieldset",t._g({ref:"fields",attrs:{disabled:t.disabled,fields:t.fields,novalidate:t.novalidate},model:{value:t.value,callback:function(e){t.value=e},expression:"value"}},t.listeners))]),t._t("footer"),n("input",{ref:"submitter",staticClass:"k-form-submitter",attrs:{type:"submit"}})],2)},ui=[],ci={props:{disabled:Boolean,config:Object,fields:{type:[Array,Object],default:function(){return{}}},novalidate:{type:Boolean,default:!1},value:{type:Object,default:function(){return{}}}},data:function(){return{errors:{},listeners:Object(k["a"])({},this.$listeners,{submit:this.onSubmit})}},methods:{focus:function(t){this.$refs.fields&&this.$refs.fields.focus&&this.$refs.fields.focus(t)},onSubmit:function(){this.$emit("submit",this.value)},submit:function(){this.$refs.submitter.click()}}},di=ci,pi=(n("5d33"),Object(u["a"])(di,li,ui,!1,null,null,null)),fi=pi.exports,hi=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("nav",{staticClass:"k-form-buttons",attrs:{"data-theme":t.mode}},["unlock"===t.mode?n("k-view",[n("p",{staticClass:"k-form-lock-info"},[t._v("\n "+t._s(t.$t("lock.isUnlocked"))+"\n ")]),n("span",{staticClass:"k-form-lock-buttons"},[n("k-button",{staticClass:"k-form-button",attrs:{icon:"download"},on:{click:t.onDownload}},[t._v("\n "+t._s(t.$t("download"))+"\n ")]),n("k-button",{staticClass:"k-form-button",attrs:{icon:"check"},on:{click:t.onResolve}},[t._v("\n "+t._s(t.$t("confirm"))+"\n ")])],1)]):"lock"===t.mode?n("k-view",[n("p",{staticClass:"k-form-lock-info"},[n("k-icon",{attrs:{type:"lock"}}),n("span",{domProps:{innerHTML:t._s(t.$t("lock.isLocked",{email:t.form.lock.email}))}})],1),n("k-button",{staticClass:"k-form-button",attrs:{disabled:!t.form.lock.unlockable,icon:"unlock"},on:{click:t.setUnlock}},[t._v("\n "+t._s(t.$t("lock.unlock"))+"\n ")])],1):"changes"===t.mode?n("k-view",[n("k-button",{staticClass:"k-form-button",attrs:{disabled:t.isDisabled,icon:"undo"},on:{click:t.onRevert}},[t._v("\n "+t._s(t.$t("revert"))+"\n ")]),n("k-button",{staticClass:"k-form-button",attrs:{disabled:t.isDisabled,icon:"check"},on:{click:t.onSave}},[t._v("\n "+t._s(t.$t("save"))+"\n ")])],1):t._e()],1)},mi=[],gi=n("75fc"),bi={data:function(){return{supportsLocking:!0}},computed:{api:function(){return{lock:[this.$route.path+"/lock",null,null,!0],unlock:[this.$route.path+"/unlock",null,null,!0]}},hasChanges:function(){return this.$store.getters["form/hasChanges"](this.id)},form:function(){return{lock:this.$store.getters["form/lock"],unlock:this.$store.getters["form/unlock"]}},id:function(){return this.$store.getters["form/current"]},isDisabled:function(){return this.$store.getters["form/isDisabled"]},isLocked:function(){return null!==this.form.lock},isUnlocked:function(){return null!==this.form.unlock},mode:function(){return!0===this.isUnlocked?"unlock":!0===this.isLocked?"lock":!0===this.hasChanges?"changes":void 0}},watch:{hasChanges:function(t,e){if(!1===e&&!0===t)return this.$store.dispatch("heartbeat/remove",this.getLock),void this.$store.dispatch("heartbeat/add",[this.setLock,40]);this.id&&!0===e&&!1===t&&this.removeLock()},id:function(){this.id&&!1===this.hasChanges&&this.$store.dispatch("heartbeat/add",[this.getLock,15])}},created:function(){this.$events.$on("keydown.cmd.s",this.onSave)},destroyed:function(){this.$events.$off("keydown.cmd.s",this.onSave)},methods:{getLock:function(){var t,e=this;return(t=this.$api).get.apply(t,Object(gi["a"])(this.api.lock)).then(function(t){if(!1===t.supported)return e.supportsLocking=!1,void e.$store.dispatch("heartbeat/remove",e.getLock);!1===t.locked?(e.isLocked&&e.form.lock.user!==e.$store.state.user.current.id&&e.$events.$emit("model.reload"),e.$store.dispatch("form/lock",null)):e.$store.dispatch("form/lock",t.locked)})},setLock:function(){var t,e=this;!0===this.supportsLocking&&(t=this.$api).patch.apply(t,Object(gi["a"])(this.api.lock)).catch(function(){e.$store.dispatch("form/revert",e.id),e.$store.dispatch("heartbeat/remove",e.setLock),e.$store.dispatch("heartbeat/add",[e.getLock,15])})},removeLock:function(){var t,e=this;!0===this.supportsLocking&&(this.$store.dispatch("heartbeat/remove",this.setLock),(t=this.$api).delete.apply(t,Object(gi["a"])(this.api.lock)).then(function(){e.$store.dispatch("form/lock",null),e.$store.dispatch("heartbeat/add",[e.getLock,15])}))},setUnlock:function(){var t,e=this;!0===this.supportsLocking&&(this.$store.dispatch("heartbeat/remove",this.setLock),(t=this.$api).patch.apply(t,Object(gi["a"])(this.api.unlock)).then(function(){e.$store.dispatch("form/lock",null),e.$store.dispatch("heartbeat/add",[e.getLock,15])}))},removeUnlock:function(){var t,e=this;!0===this.supportsLocking&&(this.$store.dispatch("heartbeat/remove",this.setLock),(t=this.$api).delete.apply(t,Object(gi["a"])(this.api.unlock)).then(function(){e.$store.dispatch("form/unlock",null),e.$store.dispatch("heartbeat/add",[e.getLock,15])}))},onDownload:function(){var t=this,e="";nt()(this.form.unlock).forEach(function(n){e+=n+": \n\n"+t.form.unlock[n],e+="\n\n----\n\n"});var n=document.createElement("a");n.setAttribute("href","data:text/plain;charset=utf-8,"+encodeURIComponent(e)),n.setAttribute("download",this.id+".txt"),n.style.display="none",document.body.appendChild(n),n.click(),document.body.removeChild(n)},onResolve:function(){this.$store.dispatch("form/revert",this.id),this.removeUnlock()},onRevert:function(){this.$store.dispatch("form/revert",this.id)},onSave:function(t){var e=this;return!!t&&(t.preventDefault&&t.preventDefault(),!1===this.hasChanges||void this.$store.dispatch("form/save",this.id).then(function(){e.$events.$emit("model.update"),e.$store.dispatch("notification/success",":)")}).catch(function(t){403!==t.code&&(t.details?e.$store.dispatch("notification/error",{message:e.$t("error.form.incomplete"),details:t.details}):e.$store.dispatch("notification/error",{message:e.$t("error.form.notSaved"),details:[{label:"Exception: "+t.exception,message:t.message}]}))}))}}},vi=bi,ki=(n("18dd"),Object(u["a"])(vi,hi,mi,!1,null,null,null)),$i=ki.exports,_i=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.storage.length>0?n("k-dropdown",{staticClass:"k-form-indicator"},[n("k-button",{staticClass:"k-topbar-button",on:{click:t.toggle}},[n("k-icon",{staticClass:"k-form-indicator-icon",attrs:{type:"edit"}})],1),n("k-dropdown-content",{ref:"list",attrs:{align:"right"}},[n("p",{staticClass:"k-form-indicator-info"},[t._v("\n "+t._s(t.$t("lock.unsaved"))+":\n ")]),n("hr"),t._l(t.entries,function(e){return n("k-dropdown-item",{key:e.link,attrs:{icon:e.icon,link:e.link}},[t._v("\n "+t._s(e.label)+"\n ")])})],2)],1):t._e()},yi=[],wi=(n("28a5"),n("f559"),{data:function(){return{isOpen:!1,entries:[],storage:[]}},computed:{store:function(){return this.$store.state.form.models}},watch:{store:{handler:function(){this.loadFromStorage()},deep:!0}},created:function(){this.loadFromStorage()},methods:{loadFromApi:function(){var t=this,e=this.storage.map(function(e){return t.$api.get(e.api,{view:"compact"},null,!0).then(function(n){return e.id.startsWith("pages/")?{icon:"page",label:n.title,link:t.$api.pages.link(n.id)}:e.id.startsWith("files/")?{icon:"image",label:n.filename,link:n.link}:e.id.startsWith("users/")?{icon:"user",label:n.email,link:t.$api.users.link(n.id)}:void 0})});return Ye.a.all(e).then(function(e){t.entries=e})},loadFromStorage:function(){var t=nt()(localStorage);t=t.filter(function(t){return t.startsWith("kirby$form$")}),this.storage=t.map(function(t){return Object(k["a"])({},JSON.parse(localStorage.getItem(t)),{id:t.split("kirby$form$")[1]})}),this.storage=this.storage.filter(function(t){return nt()(t.changes||{}).length>0})},toggle:function(){var t=this;this.isOpen=!this.isOpen,!0===this.isOpen?this.loadFromApi().then(function(){t.$refs.list.toggle()}):this.$refs.list.toggle()}}}),xi=wi,Oi=(n("9e26"),Object(u["a"])(xi,_i,yi,!1,null,null,null)),Ci=Oi.exports,Si=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{class:"k-field k-field-name-"+t.name,attrs:{"data-disabled":t.disabled},on:{focusin:function(e){return t.$emit("focus",e)},focusout:function(e){return t.$emit("blur",e)}}},[t._t("header",[n("header",{staticClass:"k-field-header"},[t._t("label",[n("label",{staticClass:"k-field-label",attrs:{for:t.input}},[t._v(t._s(t.labelText)+" "),t.required?n("abbr",{attrs:{title:"This field is required"}},[t._v("*")]):t._e()])]),t._t("options"),t._t("counter",[t.counter?n("k-counter",t._b({staticClass:"k-field-counter",attrs:{required:t.required}},"k-counter",t.counter,!1)):t._e()])],2)]),t._t("default"),t._t("footer",[t.help||t.$slots.help?n("footer",{staticClass:"k-field-footer"},[t._t("help",[t.help?n("k-text",{staticClass:"k-field-help",attrs:{theme:"help"},domProps:{innerHTML:t._s(t.help)}}):t._e()])],2):t._e()])],2)},Ei=[],ji={inheritAttrs:!1,props:{counter:[Boolean,Object],disabled:Boolean,endpoints:Object,help:String,input:[String,Number],label:String,name:[String,Number],required:Boolean,type:String},computed:{labelText:function(){return this.label||" "}}},Ti=ji,Li=(n("a134"),Object(u["a"])(Ti,Si,Ei,!1,null,null,null)),Ii=Li.exports,qi=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("fieldset",{staticClass:"k-fieldset"},[n("k-grid",t._l(t.fields,function(e,i){return"hidden"!==e.type&&t.meetsCondition(e)?n("k-column",{key:e.signature,attrs:{width:e.width}},[n("k-error-boundary",[t.hasFieldType(e.type)?n("k-"+e.type+"-field",t._b({ref:i,refInFor:!0,tag:"component",attrs:{name:i,novalidate:t.novalidate,disabled:t.disabled||e.disabled},on:{input:function(n){return t.$emit("input",t.value,e,i)},focus:function(n){return t.$emit("focus",n,e,i)},invalid:function(n,s){return t.onInvalid(n,s,e,i)},submit:function(n){return t.$emit("submit",n,e,i)}},model:{value:t.value[i],callback:function(e){t.$set(t.value,i,e)},expression:"value[fieldName]"}},"component",e,!1)):n("k-box",{attrs:{theme:"negative"}},[n("k-text",{attrs:{size:"small"}},[t._v("\n The field type "),n("strong",[t._v('"'+t._s(i)+'"')]),t._v(" does not exist\n ")])],1)],1)],1):t._e()}),1)],1)},Ai=[],Ni={props:{config:Object,disabled:Boolean,fields:{type:[Array,Object],default:function(){return[]}},novalidate:{type:Boolean,default:!1},value:{type:Object,default:function(){return{}}}},data:function(){return{errors:{}}},methods:{focus:function(t){if(t)this.hasField(t)&&"function"===typeof this.$refs[t][0].focus&&this.$refs[t][0].focus();else{var e=nt()(this.$refs)[0];this.focus(e)}},hasFieldType:function(t){return I["a"].options.components["k-"+t+"-field"]},hasField:function(t){return this.$refs[t]&&this.$refs[t][0]},meetsCondition:function(t){var e=this;if(!t.when)return!0;var n=!0;return nt()(t.when).forEach(function(i){var s=e.value[i.toLowerCase()],a=t.when[i];s!==a&&(n=!1)}),n},onInvalid:function(t,e,n,i){this.errors[i]=e,this.$emit("invalid",this.errors)},hasErrors:function(){return nt()(this.errors).length}}},Bi=Ni,Pi=(n("862b"),Object(u["a"])(Bi,qi,Ai,!1,null,null,null)),Di=Pi.exports,Mi=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-input",attrs:{"data-disabled":t.disabled,"data-invalid":!t.novalidate&&t.isInvalid,"data-theme":t.theme,"data-type":t.type}},[t.$slots.before||t.before?n("span",{staticClass:"k-input-before",on:{click:t.focus}},[t._t("before",[t._v(t._s(t.before))])],2):t._e(),n("span",{staticClass:"k-input-element",on:{click:function(e){return e.stopPropagation(),t.focus(e)}}},[t._t("default",[n("k-"+t.type+"-input",t._g(t._b({ref:"input",tag:"component",attrs:{value:t.value}},"component",t.inputProps,!1),t.listeners))])],2),t.$slots.after||t.after?n("span",{staticClass:"k-input-after",on:{click:t.focus}},[t._t("after",[t._v(t._s(t.after))])],2):t._e(),t.$slots.icon||t.icon?n("span",{staticClass:"k-input-icon",on:{click:t.focus}},[t._t("icon",[n("k-icon",{attrs:{type:t.icon}})])],2):t._e()])},Ri=[],zi={inheritAttrs:!1,props:{after:String,before:String,disabled:Boolean,type:String,icon:[String,Boolean],invalid:Boolean,theme:String,novalidate:{type:Boolean,default:!1},value:{type:[String,Boolean,Number,Object,Array],default:null}},data:function(){var t=this;return{isInvalid:this.invalid,listeners:Object(k["a"])({},this.$listeners,{invalid:function(e,n){t.isInvalid=e,t.$emit("invalid",e,n)}}),inputProps:Object(k["a"])({},this.$props,this.$attrs)}},methods:{blur:function(t){t.relatedTarget&&!1===this.$el.contains(t.relatedTarget)&&this.$refs.input.blur&&this.$refs.input.blur()},focus:function(t){if(t&&t.target&&"INPUT"===t.target.tagName)t.target.focus();else if(this.$refs.input&&this.$refs.input.focus)this.$refs.input.focus();else{var e=this.$el.querySelector("input, select, textarea");e&&e.focus()}}}},Fi=zi,Ui=(n("c7c8"),Object(u["a"])(Fi,Mi,Ri,!1,null,null,null)),Hi=Ui.exports,Ki=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-upload"},[n("input",{ref:"input",attrs:{accept:t.options.accept,multiple:t.options.multiple,"aria-hidden":"true",type:"file",tabindex:"-1"},on:{change:t.select,click:function(t){t.stopPropagation()}}}),n("k-dialog",{ref:"dialog",attrs:{size:"medium"}},[t.errors.length>0?[n("k-headline",[t._v(t._s(t.$t("upload.errors")))]),n("ul",{staticClass:"k-upload-error-list"},t._l(t.errors,function(e,i){return n("li",{key:"error-"+i},[n("p",{staticClass:"k-upload-error-filename"},[t._v(t._s(e.file.name))]),n("p",{staticClass:"k-upload-error-message"},[t._v(t._s(e.message))])])}),0)]:[n("k-headline",[t._v(t._s(t.$t("upload.progress")))]),n("ul",{staticClass:"k-upload-list"},t._l(t.files,function(e,i){return n("li",{key:"file-"+i},[n("k-progress",{ref:e.name,refInFor:!0}),n("p",{staticClass:"k-upload-list-filename"},[t._v(t._s(e.name))]),n("p",[t._v(t._s(t.errors[e.name]))])],1)}),0)],n("template",{slot:"footer"},[t.errors.length>0?[n("k-button-group",[n("k-button",{attrs:{icon:"check"},on:{click:function(e){return t.$refs.dialog.close()}}},[t._v("\n "+t._s(t.$t("confirm"))+"\n ")])],1)]:t._e()],2)],2)],1)},Vi=[],Yi=n("5176"),Wi=n.n(Yi),Gi=function(t,e){var n={url:"/",field:"file",method:"POST",accept:"text",attributes:{},complete:function(){},error:function(){},success:function(){},progress:function(){}},i=Wi()(n,e),s=new FormData;s.append(i.field,t,t.name),i.attributes&&nt()(i.attributes).forEach(function(t){s.append(t,i.attributes[t])});var a=new XMLHttpRequest,o=function(e){if(e.lengthComputable&&i.progress){var n=Math.max(0,Math.min(100,e.loaded/e.total*100));i.progress(a,t,Math.ceil(n))}};a.addEventListener("loadstart",o),a.addEventListener("progress",o),a.addEventListener("load",function(e){var n=null;try{n=JSON.parse(e.target.response)}catch(s){n={status:"error",message:"The file could not be uploaded"}}n.status&&"error"===n.status?i.error(a,t,n):(i.success(a,t,n),i.progress(a,t,100))}),a.addEventListener("error",function(e){var n=JSON.parse(e.target.response);i.error(a,t,n),i.progress(a,t,100)}),a.open("POST",i.url,!0),i.headers&&nt()(i.headers).forEach(function(t){var e=i.headers[t];a.setRequestHeader(t,e)}),a.send(s)},Ji={props:{url:{type:String},accept:{type:String,default:"*"},attributes:{type:Object},multiple:{type:Boolean,default:!0},max:{type:Number}},data:function(){return{options:this.$props,completed:{},errors:[],files:[],total:0}},methods:{open:function(t){var e=this;this.params(t),setTimeout(function(){e.$refs.input.click()},1)},params:function(t){this.options=Wi()({},this.$props,t)},select:function(t){this.upload(t.target.files)},drop:function(t,e){this.params(e),this.upload(t)},upload:function(t){var e=this;this.$refs.dialog.open(),this.files=Object(gi["a"])(t),this.completed={},this.errors=[],this.hasErrors=!1,this.options.max&&(this.files=this.files.slice(0,this.options.max)),this.total=this.files.length,this.files.forEach(function(t){Gi(t,{url:e.options.url,attributes:e.options.attributes,headers:{"X-CSRF":window.panel.csrf},progress:function(t,n,i){e.$refs[n.name]&&e.$refs[n.name][0]&&e.$refs[n.name][0].set(i)},success:function(t,n,i){e.complete(n,i.data)},error:function(t,n,i){e.errors.push({file:n,message:i.message}),e.complete(n,i.data)}})})},complete:function(t,e){var n=this;if(this.completed[t.name]=e,nt()(this.completed).length==this.total){if(this.$refs.input.value="",this.errors.length>0)return this.$forceUpdate(),void this.$emit("error",this.files);setTimeout(function(){n.$refs.dialog.close(),n.$emit("success",n.files,kt()(n.completed))},250)}}}},Zi=Ji,Xi=(n("5aee"),Object(u["a"])(Zi,Ki,Vi,!1,null,null,null)),Qi=Xi.exports,ts=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("label",{staticClass:"k-checkbox-input",on:{click:function(t){t.stopPropagation()}}},[n("input",{ref:"input",staticClass:"k-checkbox-input-native",attrs:{disabled:t.disabled,id:t.id,type:"checkbox"},domProps:{checked:t.value},on:{change:function(e){return t.onChange(e.target.checked)}}}),n("span",{staticClass:"k-checkbox-input-icon",attrs:{"aria-hidden":"true"}},[n("svg",{attrs:{width:"12",height:"10",viewBox:"0 0 12 10",xmlns:"http://www.w3.org/2000/svg"}},[n("path",{attrs:{d:"M1 5l3.3 3L11 1","stroke-width":"2",fill:"none","fill-rule":"evenodd"}})])]),n("span",{staticClass:"k-checkbox-input-label",domProps:{innerHTML:t._s(t.label)}})])},es=[],ns=n("b5ae"),is={inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[Number,String],label:String,required:Boolean,value:Boolean},watch:{value:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$refs.input.focus()},onChange:function(t){this.$emit("input",t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},select:function(){this.focus()}},validations:function(){return{value:{required:!this.required||ns["required"]}}}},ss=is,as=(n("42e4"),Object(u["a"])(ss,ts,es,!1,null,null,null)),os=as.exports,rs=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"k-checkboxes-input",style:"--columns:"+t.columns},t._l(t.options,function(e,i){return n("li",{key:i},[n("k-checkbox-input",{attrs:{id:t.id+"-"+i,label:e.text,value:-1!==t.selected.indexOf(e.value)},on:{input:function(n){return t.onInput(e.value,n)}}})],1)}),0)},ls=[],us={inheritAttrs:!1,props:{autofocus:Boolean,columns:Number,disabled:Boolean,id:{type:[Number,String],default:function(){return this._uid}},max:Number,min:Number,options:Array,required:Boolean,value:{type:[Array,Object],default:function(){return[]}}},data:function(){return{selected:this.valueToArray(this.value)}},watch:{value:function(t){this.selected=this.valueToArray(t)},selected:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$el.querySelector("input").focus()},onInput:function(t,e){if(!0===e)this.selected.push(t);else{var n=this.selected.indexOf(t);-1!==n&&this.selected.splice(n,1)}this.$emit("input",this.selected)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},select:function(){this.focus()},valueToArray:function(t){return!0===_t()(t)?t:"string"===typeof t?String(t).split(","):"object"===Object(zt["a"])(t)?kt()(t):void 0}},validations:function(){return{selected:{required:!this.required||ns["required"],min:!this.min||Object(ns["minLength"])(this.min),max:!this.max||Object(ns["maxLength"])(this.max)}}}},cs=us,ds=Object(u["a"])(cs,rs,ls,!1,null,null,null),ps=ds.exports,fs=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-date-input"},[n("k-select-input",{ref:"years",attrs:{"aria-label":t.$t("year"),options:t.years,disabled:t.disabled,required:t.required,value:t.year,placeholder:"––––"},on:{input:t.setYear,invalid:t.onInvalid}}),n("span",{staticClass:"k-date-input-separator"},[t._v("-")]),n("k-select-input",{ref:"months",attrs:{"aria-label":t.$t("month"),options:t.months,disabled:t.disabled,required:t.required,value:t.month,placeholder:"––"},on:{input:t.setMonth,invalid:t.onInvalid}}),n("span",{staticClass:"k-date-input-separator"},[t._v("-")]),n("k-select-input",{ref:"days",attrs:{"aria-label":t.$t("day"),autofocus:t.autofocus,id:t.id,options:t.days,disabled:t.disabled,required:t.required,value:t.day,placeholder:"––"},on:{input:t.setDay,invalid:t.onInvalid}})],1)},hs=[],ms=n("e814"),gs=n.n(ms),bs={inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[String,Number],max:String,min:String,required:Boolean,value:String},data:function(){return{date:Jn()(this.value),minDate:this.calculate(this.min,"min"),maxDate:this.calculate(this.max,"max")}},computed:{day:function(){return isNaN(this.date.date())?"":this.date.date()},days:function(){return this.options(1,this.date.daysInMonth()||31,"days")},month:function(){return isNaN(this.date.date())?"":this.date.month()+1},months:function(){return this.options(1,12,"months")},year:function(){return isNaN(this.date.year())?"":this.date.year()},years:function(){var t=this.date.isBefore(this.minDate)?this.date.year():this.minDate.year(),e=this.date.isAfter(this.maxDate)?this.date.year():this.maxDate.year();return this.options(t,e)}},watch:{value:function(t){this.date=Jn()(t)}},methods:{calculate:function(t,e){var n={min:{run:"subtract",take:"startOf"},max:{run:"add",take:"endOf"}}[e],i=t?Jn()(t):null;return i&&!1!==i.isValid()||(i=Jn()()[n.run](10,"year")[n.take]("year")),i},focus:function(){this.$refs.years.focus()},onInput:function(){!1!==this.date.isValid()?this.$emit("input",this.date.toISOString()):this.$emit("input","")},onInvalid:function(t,e){this.$emit("invalid",t,e)},options:function(t,e){for(var n=[],i=t;i<=e;i++)n.push({value:i,text:Zn(i)});return n},set:function(t,e){if(""===e||null===e||!1===e||-1===e)return this.setInvalid(),void this.onInput();if(!1===this.date.isValid())return this.setInitialDate(t,e),void this.onInput();var n=this.date,i=this.date.date();this.date=this.date.set(t,gs()(e)),"month"===t&&this.date.date()!==i&&(this.date=n.set("date",1).set("month",e).endOf("month")),this.onInput()},setInvalid:function(){this.date=Jn()("invalid")},setInitialDate:function(t,e){var n=Jn()();return this.date=Jn()().set(t,gs()(e)),"date"===t&&n.month()!==this.date.month()&&(this.date=n.endOf("month")),this.date},setDay:function(t){this.set("date",t)},setMonth:function(t){this.set("month",t-1)},setYear:function(t){this.set("year",t)}}},vs=bs,ks=(n("6ab3"),Object(u["a"])(vs,fs,hs,!1,null,null,null)),$s=ks.exports,_s=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-datetime-input"},[n("k-date-input",{ref:"dateInput",attrs:{autofocus:t.autofocus,required:t.required,id:t.id,min:t.min,max:t.max,disabled:t.disabled,value:t.dateValue},on:{input:t.setDate}}),n("k-time-input",t._b({ref:"timeInput",attrs:{required:t.required,disabled:t.disabled,value:t.timeValue},on:{input:t.setTime}},"k-time-input",t.timeOptions,!1))],1)},ys=[],ws={inheritAttrs:!1,props:Object(k["a"])({},$s.props,{time:{type:[Boolean,Object],default:function(){return{}}},value:String}),data:function(){return{dateValue:this.parseDate(this.value),timeValue:this.parseTime(this.value),timeOptions:this.setTimeOptions()}},watch:{value:function(t){this.dateValue=this.parseDate(t),this.timeValue=this.parseTime(t),this.onInvalid()}},mounted:function(){this.onInvalid()},methods:{focus:function(){this.$refs.dateInput.focus()},onInput:function(){if(this.timeValue&&this.dateValue){var t=this.dateValue+"T"+this.timeValue+":00";this.$emit("input",t)}else this.$emit("input","")},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},parseDate:function(t){var e=Jn()(t);return e.isValid()?e.format("YYYY-MM-DD"):null},parseTime:function(t){var e=Jn()(t);return e.isValid()?e.format("HH:mm"):null},setDate:function(t){t&&!this.timeValue&&(this.timeValue=Jn()().format("HH:mm")),t?this.dateValue=this.parseDate(t):(this.dateValue=null,this.timeValue=null),this.onInput()},setTime:function(t){t&&!this.dateValue&&(this.dateValue=Jn()().format("YYYY-MM-DD")),t?this.timeValue=t:(this.dateValue=null,this.timeValue=null),this.onInput()},setTimeOptions:function(){return!0===this.time?{}:this.time}},validations:function(){return{value:{required:!this.required||ns["required"]}}}},xs=ws,Os=(n("4433"),Object(u["a"])(xs,_s,ys,!1,null,null,null)),Cs=Os.exports,Ss=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("input",t._g(t._b({ref:"input",staticClass:"k-text-input"},"input",{autocomplete:t.autocomplete,autofocus:t.autofocus,disabled:t.disabled,id:t.id,minlength:t.minlength,name:t.name,pattern:t.pattern,placeholder:t.placeholder,required:t.required,spellcheck:t.spellcheck,type:t.type,value:t.value},!1),t.listeners))},Es=[],js={inheritAttrs:!1,class:"k-text-input",props:{autocomplete:{type:[Boolean,String],default:"off"},autofocus:Boolean,disabled:Boolean,id:[Number,String],maxlength:Number,minlength:Number,name:[Number,String],pattern:String,placeholder:String,preselect:Boolean,required:Boolean,spellcheck:{type:[Boolean,String],default:"off"},type:{type:String,default:"text"},value:String},data:function(){var t=this;return{listeners:Object(k["a"])({},this.$listeners,{input:function(e){return t.onInput(e.target.value)}})}},watch:{value:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus(),this.$props.preselect&&this.select()},methods:{focus:function(){this.$refs.input.focus()},onInput:function(t){this.$emit("input",t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},select:function(){this.$refs.input.select()}},validations:function(){var t=this,e=function(e){return!t.required&&0===e.length||!t.$refs.input.validity.patternMismatch};return{value:{required:!this.required||ns["required"],minLength:!this.minlength||Object(ns["minLength"])(this.minlength),maxLength:!this.maxlength||Object(ns["maxLength"])(this.maxlength),email:"email"!==this.type||ns["email"],url:"url"!==this.type||ns["url"],pattern:!this.pattern||e}}}},Ts=js,Ls=(n("cb8f"),Object(u["a"])(Ts,Ss,Es,!1,null,null,null)),Is=Ls.exports,qs={extends:Is,props:Object(k["a"])({},Is.props,{autocomplete:{type:String,default:"email"},placeholder:{type:String,default:function(){return this.$t("email.placeholder")}},type:{type:String,default:"email"}})},As=qs,Ns=Object(u["a"])(As,at,ot,!1,null,null,null),Bs=Ns.exports,Ps=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-draggable",{staticClass:"k-multiselect-input",attrs:{list:t.state,options:t.dragOptions,"data-layout":t.layout,element:"k-dropdown"},on:{end:t.onInput},nativeOn:{click:function(e){return t.$refs.dropdown.toggle(e)}}},[t._l(t.sorted,function(e){return n("k-tag",{key:e.value,ref:e.value,refInFor:!0,attrs:{removable:!0},on:{remove:function(n){return t.remove(e)}},nativeOn:{click:function(t){t.stopPropagation()},keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"left",37,e.key,["Left","ArrowLeft"])?null:"button"in e&&0!==e.button?null:t.navigate("prev")},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"right",39,e.key,["Right","ArrowRight"])?null:"button"in e&&2!==e.button?null:t.navigate("next")},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"down",40,e.key,["Down","ArrowDown"])?null:t.$refs.dropdown.open(e)}]}},[t._v("\n "+t._s(e.text)+"\n ")])}),n("k-dropdown-content",{ref:"dropdown",attrs:{slot:"footer"},on:{open:t.onOpen},nativeOn:{keydown:function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"esc",27,e.key,["Esc","Escape"])?null:(e.stopPropagation(),t.close(e))}},slot:"footer"},[t.search?n("k-dropdown-item",{staticClass:"k-multiselect-search",attrs:{icon:"search"}},[n("input",{directives:[{name:"model",rawName:"v-model",value:t.q,expression:"q"}],ref:"search",domProps:{value:t.q},on:{keydown:function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"esc",27,e.key,["Esc","Escape"])?null:(e.stopPropagation(),t.escape(e))},input:function(e){e.target.composing||(t.q=e.target.value)}}})]):t._e(),n("div",{staticClass:"k-multiselect-options"},t._l(t.filtered,function(e){return n("k-dropdown-item",{key:e.value,class:{"k-multiselect-option":!0,selected:t.isSelected(e),disabled:!t.addable},attrs:{icon:t.isSelected(e)?"check":"circle-outline"},on:{click:function(n){return t.select(e)}},nativeOn:{keydown:[function(n){return!n.type.indexOf("key")&&t._k(n.keyCode,"enter",13,n.key,"Enter")?null:(n.preventDefault(),t.select(e))},function(n){return!n.type.indexOf("key")&&t._k(n.keyCode,"space",32,n.key,[" ","Spacebar"])?null:(n.preventDefault(),t.select(e))}]}},[n("span",{domProps:{innerHTML:t._s(e.display)}}),n("span",{staticClass:"k-multiselect-value",domProps:{innerHTML:t._s(e.info)}})])}),1)],1)],2)},Ds=[],Ms=(n("20d6"),n("55dd"),{inheritAttrs:!1,props:{disabled:Boolean,id:[Number,String],max:Number,min:Number,layout:String,options:{type:Array,default:function(){return[]}},required:Boolean,search:Boolean,separator:{type:String,default:","},sort:Boolean,value:{type:Array,required:!0,default:function(){return[]}}},data:function(){return{state:this.value,q:null}},computed:{addable:function(){return!this.max||this.state.length1&&!this.sort},dragOptions:function(){return{disabled:!this.draggable,draggable:".k-tag",delay:1}},filtered:function(){if(null===this.q)return this.options.map(function(t){return Object(k["a"])({},t,{display:t.text,info:t.value})});var t=new RegExp("(".concat(RegExp.escape(this.q),")"),"ig");return this.options.filter(function(e){return e.text.match(t)||e.value.match(t)}).map(function(e){return Object(k["a"])({},e,{display:e.text.replace(t,"$1"),info:e.value.replace(t,"$1")})})},sorted:function(){var t=this;if(!1===this.sort)return this.state;var e=this.state,n=function(e){return t.options.findIndex(function(t){return t.value===e.value})};return e.sort(function(t,e){return n(t)-n(e)})}},watch:{value:function(t){this.state=t,this.onInvalid()}},mounted:function(){this.onInvalid(),this.$events.$on("click",this.close),this.$events.$on("keydown.cmd.s",this.close)},destroyed:function(){this.$events.$off("click",this.close),this.$events.$off("keydown.cmd.s",this.close)},methods:{add:function(t){this.addable&&(this.state.push(t),this.onInput())},blur:function(){this.close()},close:function(){this.$refs.dropdown.close(),this.q=null,this.$el.focus()},escape:function(){this.q?this.q=null:this.close()},focus:function(){this.$refs.dropdown.open()},index:function(t){return this.state.findIndex(function(e){return e.value===t.value})},isSelected:function(t){return-1!==this.index(t)},navigate:function(t){var e=document.activeElement;switch(t){case"prev":e&&e.previousSibling&&e.previousSibling.focus();break;case"next":e&&e.nextSibling&&e.nextSibling.focus();break}},onInput:function(){this.$emit("input",this.sorted)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},onOpen:function(){var t=this;this.$nextTick(function(){t.$refs.search&&t.$refs.search.focus()})},remove:function(t){this.state.splice(this.index(t),1),this.onInput()},select:function(t){t={text:t.text,value:t.value},this.isSelected(t)?this.remove(t):this.add(t)}},validations:function(){return{state:{required:!this.required||ns["required"],minLength:!this.min||Object(ns["minLength"])(this.min),maxLength:!this.max||Object(ns["maxLength"])(this.max)}}}}),Rs=Ms,zs=(n("11ae"),Object(u["a"])(Rs,Ps,Ds,!1,null,null,null)),Fs=zs.exports,Us=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("input",t._g(t._b({ref:"input",staticClass:"k-number-input",attrs:{type:"number"}},"input",{autofocus:t.autofocus,disabled:t.disabled,id:t.id,max:t.max,min:t.min,name:t.name,placeholder:t.placeholder,required:t.required,step:t.step,value:t.value},!1),t.listeners))},Hs=[],Ks={inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[Number,String],max:Number,min:Number,name:[Number,String],placeholder:String,preselect:Boolean,required:Boolean,step:Number,value:{type:[Number,String],default:null}},data:function(){var t=this;return{listeners:Object(k["a"])({},this.$listeners,{input:function(e){return t.onInput(e.target.value)}})}},watch:{value:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus(),this.$props.preselect&&this.select()},methods:{focus:function(){this.$refs.input.focus()},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},onInput:function(t){null!==t&&""!==t&&"-"!==t&&"-0"!==t&&(t=Number(t)),this.$emit("input",t)},select:function(){this.$refs.input.select()}},validations:function(){return{value:{required:!this.required||ns["required"],min:!this.min||Object(ns["minValue"])(this.min),max:!this.max||Object(ns["maxValue"])(this.max)}}}},Vs=Ks,Ys=(n("6018"),Object(u["a"])(Vs,Us,Hs,!1,null,null,null)),Ws=Ys.exports,Gs={extends:Is,props:Object(k["a"])({},Is.props,{autocomplete:{type:String,default:"new-password"},type:{type:String,default:"password"}})},Js=Gs,Zs=Object(u["a"])(Js,rt,lt,!1,null,null,null),Xs=Zs.exports,Qs=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"k-radio-input",style:"--columns:"+t.columns},t._l(t.options,function(e,i){return n("li",{key:i},[n("input",{staticClass:"k-radio-input-native",attrs:{id:t.id+"-"+i,name:t.id,type:"radio"},domProps:{value:e.value,checked:t.value===e.value},on:{change:function(n){return t.onInput(e.value)}}}),n("label",{attrs:{for:t.id+"-"+i}},[e.info?[n("span",{staticClass:"k-radio-input-text"},[t._v(t._s(e.text))]),n("span",{staticClass:"k-radio-input-info"},[t._v(t._s(e.info))])]:[t._v("\n "+t._s(e.text)+"\n ")]],2),e.icon?n("k-icon",{attrs:{type:e.icon}}):t._e()],1)}),0)},ta=[],ea={inheritAttrs:!1,props:{autofocus:Boolean,columns:Number,disabled:Boolean,id:{type:[Number,String],default:function(){return this._uid}},options:Array,required:Boolean,value:[String,Number,Boolean]},watch:{value:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$el.querySelector("input").focus()},onInput:function(t){this.$emit("input",t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},select:function(){this.focus()}},validations:function(){return{value:{required:!this.required||ns["required"]}}}},na=ea,ia=(n("893d"),Object(u["a"])(na,Qs,ta,!1,null,null,null)),sa=ia.exports,aa=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("label",{staticClass:"k-range-input"},[n("input",t._g(t._b({ref:"input",staticClass:"k-range-input-native",style:"--min: "+t.min+"; --max: "+t.max+"; --value: "+t.position,attrs:{type:"range"},domProps:{value:t.position}},"input",{autofocus:t.autofocus,disabled:t.disabled,id:t.id,max:t.max,min:t.min,name:t.name,required:t.required,step:t.step},!1),t.listeners)),t.tooltip?n("span",{staticClass:"k-range-input-tooltip"},[t.tooltip.before?n("span",{staticClass:"k-range-input-tooltip-before"},[t._v(t._s(t.tooltip.before))]):t._e(),n("span",{staticClass:"k-range-input-tooltip-text"},[t._v(t._s(t.label))]),t.tooltip.after?n("span",{staticClass:"k-range-input-tooltip-after"},[t._v(t._s(t.tooltip.after))]):t._e()]):t._e()])},oa=[],ra=(n("6b54"),{inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[String,Number],default:[Number,String],max:{type:Number,default:100},min:{type:Number,default:0},name:[String,Number],required:Boolean,step:{type:Number,default:1},tooltip:{type:[Boolean,Object],default:function(){return{before:null,after:null}}},value:[Number,String]},data:function(){var t=this;return{listeners:Object(k["a"])({},this.$listeners,{input:function(e){return t.onInput(e.target.value)}})}},computed:{baseline:function(){return this.min<0?0:this.min},label:function(){return this.required||this.value?this.format(this.position):"–"},position:function(){return this.value||this.default||this.baseline}},watch:{position:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$refs.input.focus()},format:function(t){var e=document.lang?document.lang.replace("_","-"):"en",n=this.step.toString().split("."),i=n.length>1?n[1].length:0;return new Intl.NumberFormat(e,{minimumFractionDigits:i}).format(t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},onInput:function(t){this.$emit("input",t)}},validations:function(){return{position:{required:!this.required||ns["required"],min:!this.min||Object(ns["minValue"])(this.min),max:!this.max||Object(ns["maxValue"])(this.max)}}}}),la=ra,ua=(n("b5d2"),Object(u["a"])(la,aa,oa,!1,null,null,null)),ca=ua.exports,da=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{staticClass:"k-select-input",attrs:{"data-disabled":t.disabled,"data-empty":""===t.selected}},[n("select",t._g({ref:"input",staticClass:"k-select-input-native",attrs:{autofocus:t.autofocus,"aria-label":t.ariaLabel,disabled:t.disabled,id:t.id,name:t.name,required:t.required},domProps:{value:t.selected}},t.listeners),[t.hasEmptyOption?n("option",{attrs:{disabled:t.required,value:""}},[t._v("\n "+t._s(t.emptyOption)+"\n ")]):t._e(),t._l(t.options,function(e){return n("option",{key:e.value,attrs:{disabled:e.disabled},domProps:{value:e.value}},[t._v("\n "+t._s(e.text)+"\n ")])})],2),t._v("\n "+t._s(t.label)+"\n")])},pa=[],fa={inheritAttrs:!1,props:{autofocus:Boolean,ariaLabel:String,default:String,disabled:Boolean,empty:{type:[Boolean,String],default:!0},id:[Number,String],name:[Number,String],placeholder:String,options:{type:Array,default:function(){return[]}},required:Boolean,value:{type:[String,Number,Boolean],default:""}},data:function(){var t=this;return{selected:this.value,listeners:Object(k["a"])({},this.$listeners,{click:function(e){return t.onClick(e)},change:function(e){return t.onInput(e.target.value)},input:function(t){}})}},computed:{emptyOption:function(){return this.placeholder||"—"},hasEmptyOption:function(){return!1!==this.empty&&!(this.required&&this.default)},label:function(){var t=this.text(this.selected);return""===this.selected||null===this.selected||null===t?this.emptyOption:t}},watch:{value:function(t){this.selected=t,this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$refs.input.focus()},onClick:function(t){t.stopPropagation(),this.$emit("click",t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},onInput:function(t){this.selected=t,this.$emit("input",this.selected)},select:function(){this.focus()},text:function(t){var e=null;return this.options.forEach(function(n){n.value==t&&(e=n.text)}),e}},validations:function(){return{selected:{required:!this.required||ns["required"]}}}},ha=fa,ma=(n("6a18"),Object(u["a"])(ha,da,pa,!1,null,null,null)),ga=ma.exports,ba=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-draggable",{ref:"box",staticClass:"k-tags-input",attrs:{list:t.tags,"data-layout":t.layout,options:t.dragOptions},on:{end:t.onInput}},[t._l(t.tags,function(e,i){return n("k-tag",{key:i,ref:e.value,refInFor:!0,attrs:{removable:!t.disabled,name:"tag"},on:{remove:function(n){return t.remove(e)}},nativeOn:{click:function(t){t.stopPropagation()},blur:function(e){return t.selectTag(null)},focus:function(n){return t.selectTag(e)},keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"left",37,e.key,["Left","ArrowLeft"])?null:"button"in e&&0!==e.button?null:t.navigate("prev")},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"right",39,e.key,["Right","ArrowRight"])?null:"button"in e&&2!==e.button?null:t.navigate("next")}],dblclick:function(n){return t.edit(e)}}},[t._v("\n "+t._s(e.text)+"\n ")])}),n("span",{staticClass:"k-tags-input-element",attrs:{slot:"footer"},slot:"footer"},[n("k-autocomplete",{ref:"autocomplete",attrs:{options:t.options,skip:t.skip},on:{select:t.addTag,leave:function(e){return t.$refs.input.focus()}}},[n("input",{directives:[{name:"model",rawName:"v-model.trim",value:t.newTag,expression:"newTag",modifiers:{trim:!0}}],ref:"input",attrs:{autofocus:t.autofocus,disabled:t.disabled||t.max&&t.tags.length>=t.max,id:t.id,name:t.name,autocomplete:"off",type:"text"},domProps:{value:t.newTag},on:{input:[function(e){e.target.composing||(t.newTag=e.target.value.trim())},function(e){return t.type(e.target.value)}],blur:[t.blurInput,function(e){return t.$forceUpdate()}],keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"s",void 0,e.key,void 0)?null:e.metaKey?t.blurInput(e):null},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"left",37,e.key,["Left","ArrowLeft"])?null:"button"in e&&0!==e.button?null:e.ctrlKey||e.shiftKey||e.altKey||e.metaKey?null:t.leaveInput(e)},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:e.ctrlKey||e.shiftKey||e.altKey||e.metaKey?null:t.enter(e)},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"tab",9,e.key,"Tab")?null:e.ctrlKey||e.shiftKey||e.altKey||e.metaKey?null:t.tab(e)},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"backspace",void 0,e.key,void 0)?null:e.ctrlKey||e.shiftKey||e.altKey||e.metaKey?null:t.leaveInput(e)}]}})])],1)],2)},va=[],ka={inheritAttrs:!1,props:{autofocus:Boolean,accept:{type:String,default:"all"},disabled:Boolean,icon:{type:[String,Boolean],default:"tag"},id:[Number,String],layout:String,max:Number,min:Number,name:[Number,String],options:{type:Array,default:function(){return[]}},required:Boolean,separator:{type:String,default:","},value:{type:Array,default:function(){return[]}}},data:function(){return{tags:this.prepareTags(this.value),selected:null,newTag:null,tagOptions:this.options.map(function(t){return t.icon="tag",t})}},computed:{dragOptions:function(){return{delay:1,disabled:!this.draggable,draggable:".k-tag"}},draggable:function(){return this.tags.length>1},skip:function(){return this.tags.map(function(t){return t.value})}},watch:{value:function(t){this.tags=this.prepareTags(t),this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{addString:function(t){var e=this;if(t)if(t=t.trim(),t.includes(this.separator))t.split(this.separator).forEach(function(t){e.addString(t)});else if(0!==t.length)if("options"===this.accept){var n=this.options.filter(function(e){return e.text===t})[0];if(!n)return;this.addTag(n)}else this.addTag({text:t,value:t})},addTag:function(t){this.addTagToIndex(t),this.$refs.autocomplete.close(),this.$refs.input.focus()},addTagToIndex:function(t){if("options"===this.accept){var e=this.options.filter(function(e){return e.value===t.value})[0];if(!e)return}-1===this.index(t)&&(!this.max||this.tags.length0&&(t.preventDefault(),this.addString(this.newTag))},type:function(t){this.newTag=t,this.$refs.autocomplete.search(t)}},validations:function(){return{tags:{required:!this.required||ns["required"],minLength:!this.min||Object(ns["minLength"])(this.min),maxLength:!this.max||Object(ns["maxLength"])(this.max)}}}},$a=ka,_a=(n("27c1"),Object(u["a"])($a,ba,va,!1,null,null,null)),ya=_a.exports,wa={extends:Is,props:Object(k["a"])({},Is.props,{autocomplete:{type:String,default:"tel"},type:{type:String,default:"tel"}})},xa=wa,Oa=Object(u["a"])(xa,ut,ct,!1,null,null,null),Ca=Oa.exports,Sa=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-textarea-input",attrs:{"data-theme":t.theme,"data-over":t.over}},[n("div",{staticClass:"k-textarea-input-wrapper"},[t.buttons&&!t.disabled?n("k-toolbar",{ref:"toolbar",attrs:{buttons:t.buttons,disabled:t.disabled,uploads:t.uploads},on:{command:t.onCommand},nativeOn:{mousedown:function(t){t.preventDefault()}}}):t._e(),n("textarea",t._b({ref:"input",staticClass:"k-textarea-input-native",attrs:{"data-font":t.font,"data-size":t.size},on:{click:t.onClick,focus:t.onFocus,input:t.onInput,keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:e.metaKey?t.onSubmit(e):null},function(e){return e.metaKey?t.onShortcut(e):null}],dragover:t.onOver,dragleave:t.onOut,drop:t.onDrop}},"textarea",{autofocus:t.autofocus,disabled:t.disabled,id:t.id,minlength:t.minlength,name:t.name,placeholder:t.placeholder,required:t.required,spellcheck:t.spellcheck,value:t.value},!1))],1),n("k-toolbar-email-dialog",{ref:"emailDialog",on:{cancel:t.cancel,submit:function(e){return t.insert(e)}}}),n("k-toolbar-link-dialog",{ref:"linkDialog",on:{cancel:t.cancel,submit:function(e){return t.insert(e)}}}),n("k-files-dialog",{ref:"fileDialog",on:{cancel:t.cancel,submit:function(e){return t.insertFile(e)}}}),t.uploads?n("k-upload",{ref:"fileUpload",on:{success:t.insertUpload}}):t._e()],1)},Ea=[],ja=n("19e9"),Ta=n.n(ja),La={inheritAttrs:!1,props:{autofocus:Boolean,buttons:{type:[Boolean,Array],default:!0},disabled:Boolean,endpoints:Object,font:String,id:[Number,String],name:[Number,String],maxlength:Number,minlength:Number,placeholder:String,preselect:Boolean,required:Boolean,size:String,spellcheck:{type:[Boolean,String],default:"off"},theme:String,uploads:[Boolean,Object,Array],value:String},data:function(){return{over:!1}},watch:{value:function(){var t=this;this.onInvalid(),this.$nextTick(function(){t.resize()})}},mounted:function(){var t=this;this.$nextTick(function(){Ta()(t.$refs.input)}),this.onInvalid(),this.$props.autofocus&&this.focus(),this.$props.preselect&&this.select()},methods:{cancel:function(){this.$refs.input.focus()},dialog:function(t){if(!this.$refs[t+"Dialog"])throw"Invalid toolbar dialog";this.$refs[t+"Dialog"].open(this.$refs.input,this.selection())},focus:function(){this.$refs.input.focus()},insert:function(t){var e=this,n=this.$refs.input,i=n.value;setTimeout(function(){if(n.focus(),document.execCommand("insertText",!1,t),n.value===i){var s=n.value.slice(0,n.selectionStart)+t+n.value.slice(n.selectionEnd);n.value=s,e.$emit("input",s)}}),this.resize()},insertFile:function(t){t&&t.length>0&&this.insert(t.map(function(t){return t.dragText}).join("\n\n"))},insertUpload:function(t,e){this.insert(e.map(function(t){return t.dragText}).join("\n\n")),this.$events.$emit("model.update")},onClick:function(){this.$refs.toolbar&&this.$refs.toolbar.close()},onCommand:function(t,e){"function"===typeof this[t]?"function"===typeof e?this[t](e(this.$refs.input,this.selection())):this[t](e):window.console.warn(t+" is not a valid command")},onDrop:function(t){if(t.dataTransfer&&!0===t.dataTransfer.types.includes("Files"))return this.$refs.fileUpload.drop(t.dataTransfer.files,{url:y.api+"/"+this.endpoints.field+"/upload",multiple:!1});var e=this.$store.state.drag;e&&"text"===e.type&&(this.focus(),this.insert(e.data))},onFocus:function(t){this.$emit("focus",t)},onInput:function(t){this.$emit("input",t.target.value)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},onOut:function(){this.$refs.input.blur(),this.over=!1},onOver:function(t){if(this.uploads&&t.dataTransfer&&!0===t.dataTransfer.types.includes("Files"))return t.dataTransfer.dropEffect="copy",this.focus(),void(this.over=!0);var e=this.$store.state.drag;e&&"text"===e.type&&(t.dataTransfer.dropEffect="copy",this.focus(),this.over=!0)},onShortcut:function(t){!1!==this.buttons&&"Meta"!==t.key&&this.$refs.toolbar&&this.$refs.toolbar.shortcut(t.key,t)},onSubmit:function(t){return this.$emit("submit",t)},prepend:function(t){this.insert(t+" "+this.selection())},resize:function(){Ta.a.update(this.$refs.input)},select:function(){this.$refs.select()},selectFile:function(){this.$refs.fileDialog.open({endpoint:this.endpoints.field+"/files",multiple:!1})},selection:function(){var t=this.$refs.input,e=t.selectionStart,n=t.selectionEnd;return t.value.substring(e,n)},uploadFile:function(){this.$refs.fileUpload.open({url:y.api+"/"+this.endpoints.field+"/upload",multiple:!1})},wrap:function(t){this.insert(t+this.selection()+t)}},validations:function(){return{value:{required:!this.required||ns["required"],minLength:!this.minlength||Object(ns["minLength"])(this.minlength),maxLength:!this.maxlength||Object(ns["maxLength"])(this.maxlength)}}}},Ia=La,qa=(n("cca8"),Object(u["a"])(Ia,Sa,Ea,!1,null,null,null)),Aa=qa.exports,Na=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-time-input"},[n("k-select-input",{ref:"hour",attrs:{id:t.id,"aria-label":t.$t("hour"),autofocus:t.autofocus,options:t.hours,required:t.required,disabled:t.disabled,placeholder:"––"},on:{input:t.setHour,invalid:t.onInvalid},model:{value:t.hour,callback:function(e){t.hour=e},expression:"hour"}}),n("span",{staticClass:"k-time-input-separator"},[t._v(":")]),n("k-select-input",{ref:"minute",attrs:{"aria-label":t.$t("minutes"),options:t.minutes,required:t.required,disabled:t.disabled,placeholder:"––"},on:{input:t.setMinute,invalid:t.onInvalid},model:{value:t.minute,callback:function(e){t.minute=e},expression:"minute"}}),12===t.notation?n("k-select-input",{ref:"meridiem",staticClass:"k-time-input-meridiem",attrs:{"aria-label":t.$t("meridiem"),empty:!1,options:[{value:"AM",text:"AM"},{value:"PM",text:"PM"}],required:t.required,disabled:t.disabled},on:{input:t.onInput},model:{value:t.meridiem,callback:function(e){t.meridiem=e},expression:"meridiem"}}):t._e()],1)},Ba=[],Pa=n("f906"),Da=n.n(Pa);Jn.a.extend(Da.a);var Ma,Ra,za={inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[String,Number],notation:{type:Number,default:24},required:Boolean,step:{type:Number,default:5},value:{type:String}},data:function(){var t=this.toObject(this.value);return{time:this.value,hour:t.hour,minute:t.minute,meridiem:t.meridiem}},computed:{hours:function(){return this.options(24===this.notation?0:1,24===this.notation?23:12)},minutes:function(){return this.options(0,59,this.step)}},watch:{value:function(t){this.time=t},time:function(t){var e=this.toObject(t);this.hour=e.hour,this.minute=e.minute,this.meridiem=e.meridiem}},methods:{focus:function(){this.$refs.hour.focus()},setHour:function(t){t&&!this.minute&&(this.minute=0),t||(this.minute=null),this.onInput()},setMinute:function(t){t&&!this.hour&&(this.hour=0),t||(this.hour=null),this.onInput()},onInput:function(){if(null!==this.hour&&null!==this.minute){var t=Zn(this.hour||0),e=Zn(this.minute||0),n=String(this.meridiem||"AM").toUpperCase(),i=24===this.notation?"".concat(t,":").concat(e,":00"):"".concat(t,":").concat(e,":00 ").concat(n),s=24===this.notation?"HH:mm:ss":"hh:mm:ss A",a=Jn()("2000-01-01 "+i,"YYYY-MM-DD "+s);this.$emit("input",a.format("HH:mm"))}else this.$emit("input","")},onInvalid:function(t,e){this.$emit("invalid",t,e)},options:function(t,e){for(var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,i=[],s=t;s<=e;s+=n)i.push({value:s,text:Zn(s)});return i},reset:function(){this.hour=null,this.minute=null,this.meridiem=null},round:function(t){return Math.floor(t/this.step)*this.step},toObject:function(t){var e=Jn()("2001-01-01 "+t+":00","YYYY-MM-DD HH:mm:ss");return t&&!1!==e.isValid()?{hour:e.format(24===this.notation?"H":"h"),minute:this.round(e.format("m")),meridiem:e.format("A")}:{hour:null,minute:null,meridiem:null}}}},Fa=za,Ua=(n("50da"),Object(u["a"])(Fa,Na,Ba,!1,null,null,null)),Ha=Ua.exports,Ka=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("label",{staticClass:"k-toggle-input",attrs:{"data-disabled":t.disabled}},[n("input",{ref:"input",staticClass:"k-toggle-input-native",attrs:{disabled:t.disabled,id:t.id,type:"checkbox"},domProps:{checked:t.value},on:{change:function(e){return t.onInput(e.target.checked)}}}),n("span",{staticClass:"k-toggle-input-label",domProps:{innerHTML:t._s(t.label)}})])},Va=[],Ya={inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[Number,String],text:{type:[Array,String],default:function(){return[this.$t("off"),this.$t("on")]}},required:Boolean,value:Boolean},computed:{label:function(){return _t()(this.text)?this.value?this.text[1]:this.text[0]:this.text}},watch:{value:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$refs.input.focus()},onEnter:function(t){"Enter"===t.key&&this.$refs.input.click()},onInput:function(t){this.$emit("input",t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},select:function(){this.$refs.input.focus()}},validations:function(){return{value:{required:!this.required||ns["required"]}}}},Wa=Ya,Ga=(n("bb41"),Object(u["a"])(Wa,Ka,Va,!1,null,null,null)),Ja=Ga.exports,Za={extends:Is,props:Object(k["a"])({},Is.props,{autocomplete:{type:String,default:"url"},type:{type:String,default:"url"}})},Xa=Za,Qa=Object(u["a"])(Xa,Ma,Ra,!1,null,null,null),to=Qa.exports,eo=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-checkboxes-field",attrs:{counter:t.counterOptions}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},no=[],io={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,ps.props,{counter:{type:Boolean,default:!0}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value&&_t()(this.value)?this.value.length:0,min:this.min,max:this.max}}},methods:{focus:function(){this.$refs.input.focus()}}},so=io,ao=Object(u["a"])(so,eo,no,!1,null,null,null),oo=ao.exports,ro=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-date-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,type:t.inputType,value:t.date,theme:"field"}},"k-input",t.$props,!1),t.listeners),[n("template",{slot:"icon"},[n("k-dropdown",[n("k-button",{staticClass:"k-input-icon-button",attrs:{icon:t.icon,tooltip:t.$t("date.select"),tabindex:"-1"},on:{click:function(e){return t.$refs.dropdown.toggle()}}}),n("k-dropdown-content",{ref:"dropdown",attrs:{align:"right"}},[n("k-calendar",{attrs:{value:t.date},on:{input:function(e){t.onInput(e),t.$refs.dropdown.close()}}})],1)],1)],1)],2)],1)},lo=[],uo={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,Cs.props,{icon:{type:String,default:"calendar"}}),data:function(){return{date:this.value,listeners:Object(k["a"])({},this.$listeners,{input:this.onInput})}},computed:{inputType:function(){return!1===this.time?"date":"datetime"}},watch:{value:function(t){this.date=t}},methods:{focus:function(){this.$refs.input.focus()},onInput:function(t){this.date=t,this.$emit("input",t)}}},co=uo,po=Object(u["a"])(co,ro,lo,!1,null,null,null),fo=po.exports,ho=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-email-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners),[t.link?n("k-button",{staticClass:"k-input-icon-button",attrs:{slot:"icon",icon:t.icon,link:"mailto:"+t.value,tooltip:t.$t("open"),tabindex:"-1",target:"_blank"},slot:"icon"}):t._e()],1)],1)},mo=[],go={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,Bs.props,{link:{type:Boolean,default:!0},icon:{type:String,default:"email"}}),methods:{focus:function(){this.$refs.input.focus()}}},bo=go,vo=Object(u["a"])(bo,ho,mo,!1,null,null,null),ko=vo.exports,$o=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-files-field"},"k-field",t.$props,!1),[t.more&&!t.disabled?n("template",{slot:"options"},[n("k-button-group",{staticClass:"k-field-options"},[t.uploads?[n("k-dropdown",[n("k-button",{ref:"pickerToggle",staticClass:"k-field-options-button",attrs:{icon:"add"},on:{click:function(e){return t.$refs.picker.toggle()}}},[t._v("\n "+t._s(t.$t("add"))+"\n ")]),n("k-dropdown-content",{ref:"picker",attrs:{align:"right"}},[n("k-dropdown-item",{attrs:{icon:"check"},on:{click:t.open}},[t._v(t._s(t.$t("select")))]),n("k-dropdown-item",{attrs:{icon:"upload"},on:{click:t.upload}},[t._v(t._s(t.$t("upload")))])],1)],1)]:[n("k-button",{staticClass:"k-field-options-button",attrs:{icon:"add"},on:{click:t.open}},[t._v(t._s(t.$t("add")))])]],2)],1):t._e(),t.selected.length?[n("k-draggable",{attrs:{element:t.elements.list,list:t.selected,"data-size":t.size,handle:!0},on:{end:t.onInput}},t._l(t.selected,function(e,i){return n(t.elements.item,{key:e.filename,tag:"component",attrs:{sortable:!t.disabled&&t.selected.length>1,text:e.text,link:e.link,info:e.info,image:e.image,icon:e.icon}},[t.disabled?t._e():n("k-button",{attrs:{slot:"options",tooltip:t.$t("remove"),icon:"remove"},on:{click:function(e){return t.remove(i)}},slot:"options"})],1)}),1)]:n("k-empty",{attrs:{layout:t.layout,icon:"image"},on:{click:t.open}},[t._v("\n "+t._s(t.empty||t.$t("field.files.empty"))+"\n ")]),n("k-files-dialog",{ref:"selector",on:{submit:t.select}}),n("k-upload",{ref:"fileUpload",on:{success:t.selectUpload}})],2)},_o=[],yo={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,{empty:String,info:String,layout:String,max:Number,multiple:Boolean,parent:String,size:String,text:String,value:{type:Array,default:function(){return[]}}}),data:function(){return{selected:this.value}},computed:{elements:function(){var t={cards:{list:"k-cards",item:"k-card"},list:{list:"k-list",item:"k-list-item"}};return t[this.layout]?t[this.layout]:t["list"]},more:function(){return!this.max||this.max>this.selected.length}},watch:{value:function(t){this.selected=t}},methods:{focus:function(){},onInput:function(){this.$emit("input",this.selected)},remove:function(t){this.selected.splice(t,1),this.onInput()},removeById:function(t){this.selected=this.selected.filter(function(e){return e.id!==t}),this.onInput()},select:function(t){var e=this;0!==t.length?(this.selected=this.selected.filter(function(e){return t.filter(function(t){return t.id===e.id}).length>0}),t.forEach(function(t){0===e.selected.filter(function(e){return t.id===e.id}).length&&e.selected.push(t)}),this.onInput()):this.selected=[]}}},wo={mixins:[yo],props:{uploads:[Boolean,Object,Array]},created:function(){this.$events.$on("file.delete",this.removeById)},destroyed:function(){this.$events.$off("file.delete",this.removeById)},methods:{prompt:function(t){t.stopPropagation(),this.uploads?this.$refs.picker.toggle():this.open()},open:function(){if(this.disabled)return!1;this.$refs.selector.open({endpoint:this.endpoints.field,max:this.max,multiple:this.multiple,selected:this.selected.map(function(t){return t.id})})},selectUpload:function(t,e){var n=this;!1===this.multiple&&(this.selected=[]),e.forEach(function(t){n.selected.push(t)}),this.onInput(),this.$events.$emit("model.update")},upload:function(){this.$refs.fileUpload.open({url:y.api+"/"+this.endpoints.field+"/upload",multiple:this.multiple,accept:this.uploads.accept})}}},xo=wo,Oo=(n("4a4b"),Object(u["a"])(xo,$o,_o,!1,null,null,null)),Co=Oo.exports,So=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-headline",{staticClass:"k-headline-field",attrs:{"data-numbered":t.numbered,size:"large"}},[t._v("\n "+t._s(t.label)+"\n")])},Eo=[],jo={props:{label:String,numbered:Boolean}},To=jo,Lo=(n("19d7"),Object(u["a"])(To,So,Eo,!1,null,null,null)),Io=Lo.exports,qo=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-field k-info-field"},[n("k-headline",[t._v(t._s(t.label))]),n("k-box",{attrs:{theme:t.theme}},[n("k-text",{domProps:{innerHTML:t._s(t.text)}})],1)],1)},Ao=[],No={props:{label:String,text:String,theme:{type:String,default:"info"}}},Bo=No,Po=(n("ddfd"),Object(u["a"])(Bo,qo,Ao,!1,null,null,null)),Do=Po.exports,Mo=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("hr",{staticClass:"k-line-field"})},Ro=[],zo=(n("718c"),{}),Fo=Object(u["a"])(zo,Mo,Ro,!1,null,null,null),Uo=Fo.exports,Ho=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-multiselect-field",attrs:{input:t._uid,counter:t.counterOptions},on:{blur:t.blur}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},Ko=[],Vo={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,Fs.props,{counter:{type:Boolean,default:!0},icon:{type:String,default:"angle-down"}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value&&_t()(this.value)?this.value.length:0,min:this.min,max:this.max}}},methods:{blur:function(t){this.$refs.input.blur(t)},focus:function(){this.$refs.input.focus()}}},Yo=Vo,Wo=Object(u["a"])(Yo,Ho,Ko,!1,null,null,null),Go=Wo.exports,Jo=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-number-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},Zo=[],Xo={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,Ws.props),methods:{focus:function(){this.$refs.input.focus()}}},Qo=Xo,tr=Object(u["a"])(Qo,Jo,Zo,!1,null,null,null),er=tr.exports,nr=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-pages-field"},"k-field",t.$props,!1),[n("k-button-group",{staticClass:"k-field-options",attrs:{slot:"options"},slot:"options"},[t.more&&!t.disabled?n("k-button",{staticClass:"k-field-options-button",attrs:{icon:"add"},on:{click:t.open}},[t._v("\n "+t._s(t.$t("select"))+"\n ")]):t._e()],1),t.selected.length?[n("k-draggable",{attrs:{element:t.elements.list,handle:!0,list:t.selected,"data-size":t.size},on:{end:t.onInput}},t._l(t.selected,function(e,i){return n(t.elements.item,{key:e.id,tag:"component",attrs:{sortable:!t.disabled&&t.selected.length>1,text:e.text,info:e.info,link:e.link,icon:e.icon,image:e.image}},[t.disabled?t._e():n("k-button",{attrs:{slot:"options",icon:"remove"},on:{click:function(e){return t.remove(i)}},slot:"options"})],1)}),1)]:n("k-empty",{attrs:{layout:t.layout,icon:"page"},on:{click:t.open}},[t._v("\n "+t._s(t.empty||t.$t("field.pages.empty"))+"\n ")]),n("k-pages-dialog",{ref:"selector",on:{submit:t.select}})],2)},ir=[],sr={mixins:[yo],methods:{open:function(){if(this.disabled)return!1;this.$refs.selector.open({endpoint:this.endpoints.field,max:this.max,multiple:this.multiple,selected:this.selected.map(function(t){return t.id})})}}},ar=sr,or=(n("7e85"),Object(u["a"])(ar,nr,ir,!1,null,null,null)),rr=or.exports,lr=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-password-field",attrs:{input:t._uid,counter:t.counterOptions}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},ur=[],cr={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,Xs.props,{counter:{type:Boolean,default:!0},minlength:{type:Number,default:8},icon:{type:String,default:"key"}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value?String(this.value).length:0,min:this.minlength,max:this.maxlength}}},methods:{focus:function(){this.$refs.input.focus()}}},dr=cr,pr=Object(u["a"])(dr,lr,ur,!1,null,null,null),fr=pr.exports,hr=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-radio-field"},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},mr=[],gr={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,sa.props),methods:{focus:function(){this.$refs.input.focus()}}},br=gr,vr=Object(u["a"])(br,hr,mr,!1,null,null,null),kr=vr.exports,$r=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-range-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},_r=[],yr={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,ca.props),methods:{focus:function(){this.$refs.input.focus()}}},wr=yr,xr=Object(u["a"])(wr,$r,_r,!1,null,null,null),Or=xr.exports,Cr=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-select-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},Sr=[],Er={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,ga.props,{icon:{type:String,default:"angle-down"}}),methods:{focus:function(){this.$refs.input.focus()}}},jr=Er,Tr=Object(u["a"])(jr,Cr,Sr,!1,null,null,null),Lr=Tr.exports,Ir=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-structure-field",nativeOn:{click:function(t){t.stopPropagation()}}},"k-field",t.$props,!1),[n("template",{slot:"options"},[t.more&&null===t.currentIndex?n("k-button",{ref:"add",attrs:{id:t._uid,icon:"add"},on:{click:t.add}},[t._v("\n "+t._s(t.$t("add"))+"\n ")]):t._e()],1),null!==t.currentIndex?[n("div",{staticClass:"k-structure-backdrop",on:{click:t.escape}}),n("section",{staticClass:"k-structure-form"},[n("k-form",{ref:"form",staticClass:"k-structure-form-fields",attrs:{fields:t.formFields},on:{input:t.onInput,submit:t.submit},model:{value:t.currentModel,callback:function(e){t.currentModel=e},expression:"currentModel"}}),n("footer",{staticClass:"k-structure-form-buttons"},[n("k-button",{staticClass:"k-structure-form-cancel-button",attrs:{icon:"cancel"},on:{click:t.close}},[t._v(t._s(t.$t("cancel")))]),"new"!==t.currentIndex?n("k-pagination",{attrs:{dropdown:!1,total:t.items.length,limit:1,page:t.currentIndex+1,details:!0,validate:t.beforePaginate},on:{paginate:t.paginate}}):t._e(),n("k-button",{staticClass:"k-structure-form-submit-button",attrs:{icon:"check"},on:{click:t.submit}},[t._v(t._s(t.$t("new"!==t.currentIndex?"confirm":"add")))])],1)],1)]:0===t.items.length?n("k-empty",{attrs:{icon:"list-bullet"},on:{click:t.add}},[t._v("\n "+t._s(t.empty||t.$t("field.structure.empty"))+"\n ")]):[n("table",{staticClass:"k-structure-table",attrs:{"data-sortable":t.isSortable}},[n("thead",[n("tr",[n("th",{staticClass:"k-structure-table-index"},[t._v("#")]),t._l(t.columns,function(e,i){return n("th",{key:i+"-header",staticClass:"k-structure-table-column",style:"width:"+t.width(e.width),attrs:{"data-align":e.align}},[t._v("\n "+t._s(e.label)+"\n ")])}),n("th")],2)]),n("k-draggable",{attrs:{list:t.items,"data-disabled":t.disabled,options:t.dragOptions,handle:!0,element:"tbody"},on:{end:t.onInput}},t._l(t.paginatedItems,function(e,i){return n("tr",{key:i,on:{click:function(t){t.stopPropagation()}}},[n("td",{staticClass:"k-structure-table-index"},[t.isSortable?n("k-sort-handle"):t._e(),n("span",{staticClass:"k-structure-table-index-number"},[t._v(t._s(t.indexOf(i)))])],1),t._l(t.columns,function(s,a){return n("td",{key:a,staticClass:"k-structure-table-column",style:"width:"+t.width(s.width),attrs:{title:s.label,"data-align":s.align},on:{click:function(e){return t.jump(i,a)}}},[!1===t.columnIsEmpty(e[a])?[t.previewExists(s.type)?n("k-"+s.type+"-field-preview",{tag:"component",attrs:{value:e[a],column:s,field:t.fields[a]}}):[n("p",{staticClass:"k-structure-table-text"},[t._v("\n "+t._s(s.before)+" "+t._s(t.displayText(t.fields[a],e[a])||"–")+" "+t._s(s.after)+"\n ")])]]:t._e()],2)}),n("td",{staticClass:"k-structure-table-option"},[n("k-button",{attrs:{tooltip:t.$t("remove"),icon:"remove"},on:{click:function(e){return t.confirmRemove(i)}}})],1)],2)}),0)],1),t.limit?n("k-pagination",t._b({on:{paginate:t.paginateItems}},"k-pagination",t.pagination,!1)):t._e(),t.disabled?t._e():n("k-dialog",{ref:"remove",attrs:{button:t.$t("delete"),theme:"negative"},on:{submit:t.remove}},[n("k-text",[t._v(t._s(t.$t("field.structure.delete.confirm")))])],1)]],2)},qr=[],Ar=n("59ad"),Nr=n.n(Ar),Br=function(t){t=t||{};var e=t.desc?-1:1,n=-e,i=/^0/,s=/\s+/g,a=/^\s+|\s+$/g,o=/[^\x00-\x80]/,r=/^0x[0-9a-f]+$/i,l=/(0x[\da-fA-F]+|(^[\+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|\d+)/g,u=/(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,c=t.insensitive?function(t){return d(""+t).replace(a,"")}:function(t){return(""+t).replace(a,"")};function d(t){return t.toLocaleLowerCase?t.toLocaleLowerCase():t.toLowerCase()}function p(t){return t.replace(l,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0")}function f(t,e){return(!t.match(i)||1===e)&&Nr()(t)||t.replace(s," ").replace(a,"")||0}return function(t,i){var s=c(t),a=c(i);if(!s&&!a)return 0;if(!s&&a)return n;if(s&&!a)return e;var l=p(s),d=p(a),h=gs()(s.match(r),16)||1!==l.length&&Date.parse(s),m=gs()(a.match(r),16)||h&&a.match(u)&&Date.parse(a)||null;if(m){if(hm)return e}for(var g=l.length,b=d.length,v=0,k=Math.max(g,b);v0)return e;if(y<0)return n;if(v===k-1)return 0}else{if($<_)return n;if($>_)return e}}return 0}},Pr=n("f499"),Dr=n.n(Pr),Mr=function(t){if(void 0!==t)return JSON.parse(Dr()(t))};Array.prototype.sortBy=function(t){var e=Br(),n=t.split(" "),i=n[0],s=n[1]||"asc";return this.sort(function(t,n){var a=String(t[i]).toLowerCase(),o=String(n[i]).toLowerCase();return"desc"===s?e(o,a):e(a,o)})};var Rr,zr,Fr,Ur,Hr={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,{columns:Object,empty:String,fields:Object,limit:Number,max:Number,min:Number,sortable:{type:Boolean,default:!0},sortBy:String,value:{type:Array,default:function(){return[]}}}),data:function(){return{items:this.makeItems(this.value),currentIndex:null,currentModel:null,trash:null,page:1}},computed:{dragOptions:function(){return{disabled:!this.isSortable,fallbackClass:"k-sortable-row-fallback"}},formFields:function(){var t=this,e={};return nt()(this.fields).forEach(function(n){var i=t.fields[n];i.section=t.name,i.endpoints={field:t.endpoints.field+"+"+n,section:t.endpoints.section,model:t.endpoints.model},e[n]=i}),e},more:function(){return!0!==this.disabled&&!(this.max&&this.items.length>=this.max)},isSortable:function(){return!this.sortBy&&(!this.limit&&(!0!==this.disabled&&(!(this.items.length<=1)&&!1!==this.sortable)))},pagination:function(){var t=0;return this.limit&&(t=(this.page-1)*this.limit),{page:this.page,offset:t,limit:this.limit,total:this.items.length,align:"center",details:!0}},paginatedItems:function(){return this.limit?this.items.slice(this.pagination.offset,this.pagination.offset+this.limit):this.items}},watch:{value:function(t){t!=this.items&&(this.items=this.makeItems(t))}},methods:{add:function(){var t=this;if(!0===this.disabled)return!1;if(null!==this.currentIndex)return this.escape(),!1;var e={};nt()(this.fields).forEach(function(n){var i=t.fields[n];null!==i.default?e[n]=Mr(i.default):e[n]=null}),this.currentIndex="new",this.currentModel=e,this.createForm()},close:function(){this.currentIndex=null,this.currentModel=null,this.$events.$off("keydown.esc",this.escape),this.$events.$off("keydown.cmd.s",this.submit),this.$store.dispatch("form/enable")},columnIsEmpty:function(t){return void 0===t||null===t||""===t||("object"===Object(zt["a"])(t)&&0===nt()(t).length&&t.constructor===Object||void 0!==t.length&&0===t.length)},confirmRemove:function(t){this.close(),this.trash=t,this.$refs.remove.open()},createForm:function(t){var e=this;this.$events.$on("keydown.esc",this.escape),this.$events.$on("keydown.cmd.s",this.submit),this.$store.dispatch("form/disable"),this.$nextTick(function(){e.$refs.form&&e.$refs.form.focus(t)})},displayText:function(t,e){switch(t.type){case"user":return e.email;case"date":var n=Jn()(e),i=!0===t.time?"YYYY-MM-DD HH:mm":"YYYY-MM-DD";return n.isValid()?n.format(i):"";case"tags":case"multiselect":return e.map(function(t){return t.text}).join(", ");case"checkboxes":return e.map(function(e){var n=e;return t.options.forEach(function(t){t.value===e&&(n=t.text)}),n}).join(", ");case"radio":case"select":var s=t.options.filter(function(t){return t.value===e})[0];return s?s.text:null}return"object"===Object(zt["a"])(e)&&null!==e?"…":e},escape:function(){var t=this;if("new"===this.currentIndex){var e=kt()(this.currentModel),n=!0;if(e.forEach(function(e){!1===t.columnIsEmpty(e)&&(n=!1)}),!0===n)return void this.close()}this.submit()},focus:function(){this.$refs.add&&this.$refs.add.focus&&this.$refs.add.focus()},indexOf:function(t){return this.limit?(this.page-1)*this.limit+t+1:t+1},isActive:function(t){return this.currentIndex===t},jump:function(t,e){this.open(t+this.pagination.offset,e)},makeItems:function(t){return!1===_t()(t)?[]:this.sort(t)},onInput:function(){this.$emit("input",this.items)},open:function(t,e){this.currentIndex=t,this.currentModel=Mr(this.items[t]),this.createForm(e)},beforePaginate:function(){return this.save(this.currentModel)},paginate:function(t){this.open(t.offset)},paginateItems:function(t){this.page=t.page},previewExists:function(t){return void 0!==I["a"].options.components["k-"+t+"-field-preview"]||void 0!==this.$options.components["k-"+t+"-field-preview"]},remove:function(){if(null===this.trash)return!1;this.items.splice(this.trash,1),this.trash=null,this.$refs.remove.close(),this.onInput(),0===this.paginatedItems.length&&this.page>1&&this.page--,this.items=this.sort(this.items)},sort:function(t){return this.sortBy?t.sortBy(this.sortBy):t},save:function(){var t=this;return null!==this.currentIndex&&void 0!==this.currentIndex?this.validate(this.currentModel).then(function(){return"new"===t.currentIndex?t.items.push(t.currentModel):t.items[t.currentIndex]=t.currentModel,t.items=t.sort(t.items),t.onInput(),!0}).catch(function(e){throw t.$store.dispatch("notification/error",{message:t.$t("error.form.incomplete"),details:e}),e}):Ye.a.resolve()},submit:function(){this.save().then(this.close).catch(function(){})},validate:function(t){return this.$api.post(this.endpoints.field+"/validate",t).then(function(t){if(t.length>0)throw t;return!0})},width:function(t){if(!t)return"auto";var e=t.toString().split("/");if(2!==e.length)return"auto";var n=Number(e[0]),i=Number(e[1]);return Nr()(100/i*n,2).toFixed(2)+"%"}}},Kr=Hr,Vr=(n("088c"),Object(u["a"])(Kr,Ir,qr,!1,null,null,null)),Yr=Vr.exports,Wr=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-tags-field",attrs:{input:t._uid,counter:t.counterOptions}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},Gr=[],Jr={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,ya.props,{counter:{type:Boolean,default:!0}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value&&_t()(this.value)?this.value.length:0,min:this.min,max:this.max}}},methods:{focus:function(){this.$refs.input.focus()}}},Zr=Jr,Xr=Object(u["a"])(Zr,Wr,Gr,!1,null,null,null),Qr=Xr.exports,tl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-tel-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},el=[],nl={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,Ca.props,{icon:{type:String,default:"phone"}}),methods:{focus:function(){this.$refs.input.focus()}}},il=nl,sl=Object(u["a"])(il,tl,el,!1,null,null,null),al=sl.exports,ol=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-text-field",attrs:{input:t._uid,counter:t.counterOptions}},"k-field",t.$props,!1),[t._t("options",null,{slot:"options"}),n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],2)},rl=[],ll={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,Is.props,{counter:{type:Boolean,default:!0}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value?String(this.value).length:0,min:this.minlength,max:this.maxlength}}},methods:{focus:function(){this.$refs.input.focus()}}},ul=ll,cl=(n("b746"),Object(u["a"])(ul,ol,rl,!1,null,null,null)),dl=cl.exports,pl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-textarea-field",attrs:{input:t._uid,counter:t.counterOptions}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,type:"textarea",theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},fl=[],hl={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,Aa.props,{counter:{type:Boolean,default:!0}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value?this.value.length:0,min:this.minlength,max:this.maxlength}}},methods:{focus:function(){this.$refs.input.focus()}}},ml=hl,gl=Object(u["a"])(ml,pl,fl,!1,null,null,null),bl=gl.exports,vl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-time-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},kl=[],$l={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,Ha.props,{icon:{type:String,default:"clock"}}),methods:{focus:function(){this.$refs.input.focus()}}},_l=$l,yl=Object(u["a"])(_l,vl,kl,!1,null,null,null),wl=yl.exports,xl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-toggle-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},Ol=[],Cl={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,Ja.props),methods:{focus:function(){this.$refs.input.focus()}}},Sl=Cl,El=Object(u["a"])(Sl,xl,Ol,!1,null,null,null),jl=El.exports,Tl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-url-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners),[t.link?n("k-button",{staticClass:"k-input-icon-button",attrs:{slot:"icon",icon:t.icon,link:t.value,tooltip:t.$t("open"),tabindex:"-1",target:"_blank"},slot:"icon"}):t._e()],1)],1)},Ll=[],Il={inheritAttrs:!1,props:Object(k["a"])({},Ii.props,Hi.props,to.props,{link:{type:Boolean,default:!0},icon:{type:String,default:"url"}}),methods:{focus:function(){this.$refs.input.focus()}}},ql=Il,Al=Object(u["a"])(ql,Tl,Ll,!1,null,null,null),Nl=Al.exports,Bl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-users-field"},"k-field",t.$props,!1),[n("k-button-group",{staticClass:"k-field-options",attrs:{slot:"options"},slot:"options"},[t.more&&!t.disabled?n("k-button",{staticClass:"k-field-options-button",attrs:{icon:"add"},on:{click:t.open}},[t._v("\n "+t._s(t.$t("select"))+"\n ")]):t._e()],1),t.selected.length?[n("k-draggable",{attrs:{element:t.elements.list,list:t.selected,handle:!0},on:{end:t.onInput}},t._l(t.selected,function(e,i){return n(t.elements.item,{key:e.email,tag:"component",attrs:{sortable:!t.disabled&&t.selected.length>1,text:e.username,info:e.info,link:t.$api.users.link(e.id),image:e.image,icon:e.icon}},[t.disabled?t._e():n("k-button",{attrs:{slot:"options",icon:"remove"},on:{click:function(e){return t.remove(i)}},slot:"options"})],1)}),1)]:n("k-empty",{attrs:{icon:"users"},on:{click:t.open}},[t._v("\n "+t._s(t.empty||t.$t("field.users.empty"))+"\n ")]),n("k-users-dialog",{ref:"selector",on:{submit:t.select}})],2)},Pl=[],Dl={mixins:[yo],methods:{open:function(){if(this.disabled)return!1;this.$refs.selector.open({endpoint:this.endpoints.field,max:this.max,multiple:this.multiple,selected:this.selected.map(function(t){return t.id})})}}},Ml=Dl,Rl=(n("7f6e"),Object(u["a"])(Ml,Bl,Pl,!1,null,null,null)),zl=Rl.exports,Fl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("nav",{staticClass:"k-toolbar"},[n("div",{staticClass:"k-toolbar-wrapper"},[n("div",{staticClass:"k-toolbar-buttons"},[t._l(t.layout,function(e,i){return[e.divider?[n("span",{key:i,staticClass:"k-toolbar-divider"})]:e.dropdown?[n("k-dropdown",{key:i},[n("k-button",{key:i,staticClass:"k-toolbar-button",attrs:{icon:e.icon,tooltip:e.label,tabindex:"-1"},on:{click:function(e){t.$refs[i+"-dropdown"][0].toggle()}}}),n("k-dropdown-content",{ref:i+"-dropdown",refInFor:!0},t._l(e.dropdown,function(e,i){return n("k-dropdown-item",{key:i,attrs:{icon:e.icon},on:{click:function(n){return t.command(e.command,e.args)}}},[t._v("\n "+t._s(e.label)+"\n ")])}),1)],1)]:[n("k-button",{key:i,staticClass:"k-toolbar-button",attrs:{icon:e.icon,tooltip:e.label,tabindex:"-1"},on:{click:function(n){return t.command(e.command,e.args)}}})]]})],2)])])},Ul=[],Hl=function(t){this.command("insert",function(e,n){var i=[];return n.split("\n").forEach(function(e,n){var s="ol"===t?n+1+".":"-";i.push(s+" "+e)}),i.join("\n")})},Kl={layout:["headlines","bold","italic","|","link","email","file","|","code","ul","ol"],props:{buttons:{type:[Boolean,Array],default:!0},uploads:[Boolean,Object,Array]},data:function(){var t={},e={},n=[],i=this.commands();return!1===this.buttons?t:(_t()(this.buttons)&&(n=this.buttons),!0!==_t()(this.buttons)&&(n=this.$options.layout),n.forEach(function(n,s){if("|"===n)t["divider-"+s]={divider:!0};else if(i[n]){var a=i[n];t[n]=a,a.shortcut&&(e[a.shortcut]=n)}}),{layout:t,shortcuts:e})},methods:{command:function(t,e){"function"===typeof t?t.apply(this):this.$emit("command",t,e)},close:function(){var t=this;nt()(this.$refs).forEach(function(e){var n=t.$refs[e][0];n.close&&"function"===typeof n.close&&n.close()})},fileCommandSetup:function(){var t={label:this.$t("toolbar.button.file"),icon:"attachment"};return!1===this.uploads?t.command="selectFile":t.dropdown={select:{label:this.$t("toolbar.button.file.select"),icon:"check",command:"selectFile"},upload:{label:this.$t("toolbar.button.file.upload"),icon:"upload",command:"uploadFile"}},t},commands:function(){return{headlines:{label:this.$t("toolbar.button.headings"),icon:"title",dropdown:{h1:{label:this.$t("toolbar.button.heading.1"),icon:"title",command:"prepend",args:"#"},h2:{label:this.$t("toolbar.button.heading.2"),icon:"title",command:"prepend",args:"##"},h3:{label:this.$t("toolbar.button.heading.3"),icon:"title",command:"prepend",args:"###"}}},bold:{label:this.$t("toolbar.button.bold"),icon:"bold",command:"wrap",args:"**",shortcut:"b"},italic:{label:this.$t("toolbar.button.italic"),icon:"italic",command:"wrap",args:"*",shortcut:"i"},link:{label:this.$t("toolbar.button.link"),icon:"url",shortcut:"l",command:"dialog",args:"link"},email:{label:this.$t("toolbar.button.email"),icon:"email",shortcut:"e",command:"dialog",args:"email"},file:this.fileCommandSetup(),code:{label:this.$t("toolbar.button.code"),icon:"code",command:"wrap",args:"`"},ul:{label:this.$t("toolbar.button.ul"),icon:"list-bullet",command:function(){return Hl.apply(this,["ul"])}},ol:{label:this.$t("toolbar.button.ol"),icon:"list-numbers",command:function(){return Hl.apply(this,["ol"])}}}},shortcut:function(t,e){if(this.shortcuts[t]){var n=this.layout[this.shortcuts[t]];if(!n)return!1;e.preventDefault(),this.command(n.command,n.args)}}}},Vl=Kl,Yl=(n("df0d"),Object(u["a"])(Vl,Fl,Ul,!1,null,null,null)),Wl=Yl.exports,Gl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("insert")},on:{close:t.cancel,submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.value,callback:function(e){t.value=e},expression:"value"}})],1)},Jl=[],Zl={data:function(){return{value:{email:null,text:null},fields:{email:{label:this.$t("email"),type:"email"},text:{label:this.$t("link.text"),type:"text"}}}},computed:{kirbytext:function(){return this.$store.state.system.info.kirbytext}},methods:{open:function(t,e){this.value.text=e,this.$refs.dialog.open()},cancel:function(){this.$emit("cancel")},createKirbytext:function(){var t=this.value.email||"";return this.value.text&&this.value.text.length>0?"(email: ".concat(t," text: ").concat(this.value.text,")"):"(email: ".concat(t,")")},createMarkdown:function(){var t=this.value.email||"";return this.value.text&&this.value.text.length>0?"[".concat(this.value.text,"](mailto:").concat(t,")"):"<".concat(t,">")},submit:function(){this.$emit("submit",this.kirbytext?this.createKirbytext():this.createMarkdown()),this.value={email:null,text:null},this.$refs.dialog.close()}}},Xl=Zl,Ql=Object(u["a"])(Xl,Gl,Jl,!1,null,null,null),tu=Ql.exports,eu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("insert")},on:{close:t.cancel,submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.value,callback:function(e){t.value=e},expression:"value"}})],1)},nu=[],iu={data:function(){return{value:{url:null,text:null},fields:{url:{label:this.$t("link"),type:"text",placeholder:this.$t("url.placeholder"),icon:"url"},text:{label:this.$t("link.text"),type:"text"}}}},computed:{kirbytext:function(){return this.$store.state.system.info.kirbytext}},methods:{open:function(t,e){this.value.text=e,this.$refs.dialog.open()},cancel:function(){this.$emit("cancel")},createKirbytext:function(){return this.value.text.length>0?"(link: ".concat(this.value.url," text: ").concat(this.value.text,")"):"(link: ".concat(this.value.url,")")},createMarkdown:function(){return this.value.text.length>0?"[".concat(this.value.text,"](").concat(this.value.url,")"):"<".concat(this.value.url,">")},submit:function(){this.$emit("submit",this.kirbytext?this.createKirbytext():this.createMarkdown()),this.value={url:null,text:null},this.$refs.dialog.close()}}},su=iu,au=Object(u["a"])(su,eu,nu,!1,null,null,null),ou=au.exports,ru=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.value?n("ul",{staticClass:"k-files-field-preview"},t._l(t.value,function(e){return n("li",{key:e.url},[n("k-link",{attrs:{title:e.filename,to:e.link},nativeOn:{click:function(t){t.stopPropagation()}}},["image"===e.type?n("k-image",t._b({},"k-image",t.imageOptions(e),!1)):n("k-icon",t._b({},"k-icon",e.icon,!1))],1)],1)}),0):t._e()},lu=[],uu=function(t){if(!t)return!1;var e=null,n=null;return t.list?(e=t.list.url,n=t.list.srcset):(e=t.url,n=t.srcset),!!e&&{src:e,srcset:n,back:t.back||"black",cover:t.cover}},cu={props:{value:Array,field:Object},methods:{imageOptions:function(t){var e=uu(t.image);return e.src?Object(k["a"])({},e,{back:"pattern",cover:!1},this.field.image||{}):{src:t.url}}}},du=cu,pu=(n("21dc"),Object(u["a"])(du,ru,lu,!1,null,null,null)),fu=pu.exports,hu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("p",{staticClass:"k-url-field-preview"},[t._v("\n "+t._s(t.column.before)+"\n "),n("k-link",{attrs:{to:t.link,target:"_blank"},nativeOn:{click:function(t){t.stopPropagation()}}},[t._v(t._s(t.value))]),t._v("\n "+t._s(t.column.after)+"\n")],1)},mu=[],gu={props:{column:{type:Object,default:function(){return{}}},value:String},computed:{link:function(){return this.value}}},bu=gu,vu=(n("977f"),Object(u["a"])(bu,hu,mu,!1,null,null,null)),ku=vu.exports,$u={extends:ku,computed:{link:function(){return"mailto:"+this.value}}},_u=$u,yu=Object(u["a"])(_u,Rr,zr,!1,null,null,null),wu=yu.exports,xu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.value?n("ul",{staticClass:"k-pages-field-preview"},t._l(t.value,function(e){return n("li",{key:e.id},[n("figure",[n("k-link",{attrs:{title:e.id,to:t.$api.pages.link(e.id)},nativeOn:{click:function(t){t.stopPropagation()}}},[n("k-icon",{staticClass:"k-pages-field-preview-image",attrs:{type:"page",back:"pattern"}}),n("figcaption",[t._v("\n "+t._s(e.text)+"\n ")])],1)],1)])}),0):t._e()},Ou=[],Cu={props:{value:Array}},Su=Cu,Eu=(n("d0c1"),Object(u["a"])(Su,xu,Ou,!1,null,null,null)),ju=Eu.exports,Tu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.value?n("ul",{staticClass:"k-users-field-preview"},t._l(t.value,function(e){return n("li",{key:e.email},[n("figure",[n("k-link",{attrs:{title:e.email,to:t.$api.users.link(e.id)},nativeOn:{click:function(t){t.stopPropagation()}}},[e.avatar?n("k-image",{staticClass:"k-users-field-preview-avatar",attrs:{src:e.avatar.url,back:"pattern"}}):n("k-icon",{staticClass:"k-users-field-preview-avatar",attrs:{type:"user",back:"pattern"}}),n("figcaption",[t._v("\n "+t._s(e.username)+"\n ")])],1)],1)])}),0):t._e()},Lu=[],Iu={props:{value:Array}},qu=Iu,Au=(n("3a85"),Object(u["a"])(qu,Tu,Lu,!1,null,null,null)),Nu=Au.exports,Bu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-bar"},[t.$slots.left?n("div",{staticClass:"k-bar-slot",attrs:{"data-position":"left"}},[t._t("left")],2):t._e(),t.$slots.center?n("div",{staticClass:"k-bar-slot",attrs:{"data-position":"center"}},[t._t("center")],2):t._e(),t.$slots.right?n("div",{staticClass:"k-bar-slot",attrs:{"data-position":"right"}},[t._t("right")],2):t._e()])},Pu=[],Du=(n("6f7b"),{}),Mu=Object(u["a"])(Du,Bu,Pu,!1,null,null,null),Ru=Mu.exports,zu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",t._g({staticClass:"k-box",attrs:{"data-theme":t.theme}},t.$listeners),[t._t("default",[n("k-text",{domProps:{innerHTML:t._s(t.text)}})])],2)},Fu=[],Uu={props:{theme:String,text:String}},Hu=Uu,Ku=(n("7dc7"),Object(u["a"])(Hu,zu,Fu,!1,null,null,null)),Vu=Ku.exports,Yu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("figure",t._g({staticClass:"k-card"},t.$listeners),[t.sortable?n("k-sort-handle"):t._e(),n(t.wrapper,{tag:"component",attrs:{to:t.link,target:t.target}},[t.imageOptions?n("k-image",t._b({staticClass:"k-card-image"},"k-image",t.imageOptions,!1)):n("span",{staticClass:"k-card-icon",style:"padding-bottom:"+t.ratioPadding},[n("k-icon",t._b({},"k-icon",t.icon,!1))],1),n("figcaption",{staticClass:"k-card-content"},[n("span",{staticClass:"k-card-text",attrs:{"data-noinfo":!t.info}},[t._v(t._s(t.text))]),t.info?n("span",{staticClass:"k-card-info",domProps:{innerHTML:t._s(t.info)}}):t._e()])],1),n("nav",{staticClass:"k-card-options"},[t.flag?n("k-button",t._b({staticClass:"k-card-options-button",on:{click:t.flag.click}},"k-button",t.flag,!1)):t._e(),t._t("options",[t.options?n("k-button",{staticClass:"k-card-options-button",attrs:{tooltip:t.$t("options"),icon:"dots"},on:{click:function(e){return e.stopPropagation(),t.$refs.dropdown.toggle()}}}):t._e(),n("k-dropdown-content",{ref:"dropdown",staticClass:"k-card-options-dropdown",attrs:{options:t.options,align:"right"},on:{action:function(e){return t.$emit("action",e)}}})])],2)],1)},Wu=[],Gu=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"3/2",e=String(t).split("/");if(2!==e.length)return"100%";var n=Number(e[0]),i=Number(e[1]),s=100;return 0!==n&&0!==i&&(s=100/n*i),s+"%"},Ju={inheritAttrs:!1,props:{column:String,flag:Object,icon:{type:Object,default:function(){return{type:"file",back:"black"}}},image:Object,info:String,link:String,options:[Array,Function],sortable:Boolean,target:String,text:String},computed:{wrapper:function(){return this.link?"k-link":"div"},ratioPadding:function(){return this.icon&&this.icon.ratio?Gu(this.icon.ratio):Gu("3/2")},imageOptions:function(){if(!this.image)return!1;var t=null,e=null;return this.image.cards?(t=this.image.cards.url,e=this.image.cards.srcset):(t=this.image.url,e=this.image.srcset),!!t&&{src:t,srcset:e,back:this.image.back||"black",cover:this.image.cover,ratio:this.image.ratio||"3/2",sizes:this.getSizes(this.column)}}},methods:{getSizes:function(t){switch(t){case"1/2":case"2/4":return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 44em, 27em";case"1/3":return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 29.333em, 27em";case"1/4":return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 22em, 27em";case"2/3":return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 27em, 27em";case"3/4":return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 66em, 27em";default:return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 88em, 27em"}}}},Zu=Ju,Xu=(n("c119"),Object(u["a"])(Zu,Yu,Wu,!1,null,null,null)),Qu=Xu.exports,tc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-cards"},[t._t("default",t._l(t.cards,function(e,i){return n("k-card",t._g(t._b({key:i},"k-card",e,!1),t.$listeners))}))],2)},ec=[],nc={props:{cards:Array}},ic=nc,sc=(n("f56d"),Object(u["a"])(ic,tc,ec,!1,null,null,null)),ac=sc.exports,oc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-collection",attrs:{"data-layout":t.layout}},[n("k-draggable",{attrs:{list:t.items,options:t.dragOptions,element:t.elements.list,"data-size":t.size,handle:!0},on:{change:function(e){return t.$emit("change",e)},end:t.onEnd}},t._l(t.items,function(e,i){return n(t.elements.item,t._b({key:i,tag:"component",class:{"k-draggable-item":e.sortable},on:{action:function(n){return t.$emit("action",e,n)},dragstart:function(n){return t.onDragStart(n,e.dragText)}}},"component",e,!1))}),1),t.hasFooter?n("footer",{staticClass:"k-collection-footer"},[t.help?n("k-text",{staticClass:"k-collection-help",attrs:{theme:"help"},domProps:{innerHTML:t._s(t.help)}}):t._e(),n("div",{staticClass:"k-collection-pagination"},[t.hasPagination?n("k-pagination",t._b({on:{paginate:function(e){return t.$emit("paginate",e)}}},"k-pagination",t.paginationOptions,!1)):t._e()],1)],1):t._e()],1)},rc=[],lc={props:{help:String,items:{type:[Array,Object],default:function(){return[]}},layout:{type:String,default:"list"},size:String,sortable:Boolean,pagination:{type:[Boolean,Object],default:function(){return!1}}},computed:{hasPagination:function(){return!1!==this.pagination&&(!0!==this.paginationOptions.hide&&!(this.pagination.total<=this.pagination.limit))},hasFooter:function(){return!(!this.hasPagination&&!this.help)},dragOptions:function(){return{sort:this.sortable,disabled:!1===this.sortable,draggable:".k-draggable-item"}},elements:function(){var t={cards:{list:"k-cards",item:"k-card"},list:{list:"k-list",item:"k-list-item"}};return t[this.layout]?t[this.layout]:t["list"]},paginationOptions:function(){var t="object"!==Object(zt["a"])(this.pagination)?{}:this.pagination;return Object(k["a"])({limit:10,details:!0,keys:!1,total:0,hide:!1},t)}},watch:{$props:function(){this.$forceUpdate()}},over:null,methods:{onEnd:function(){this.over&&this.over.removeAttribute("data-over"),this.$emit("sort",this.items)},onDragStart:function(t,e){this.$store.dispatch("drag",{type:"text",data:e})}}},uc=lc,cc=(n("8c28"),Object(u["a"])(uc,oc,rc,!1,null,null,null)),dc=cc.exports,pc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-column",attrs:{"data-width":t.width}},[t._t("default")],2)},fc=[],hc={props:{width:String}},mc=hc,gc=(n("c9cb"),Object(u["a"])(mc,pc,fc,!1,null,null,null)),bc=gc.exports,vc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-dropzone",attrs:{"data-dragging":t.dragging,"data-over":t.over},on:{dragenter:t.onEnter,dragleave:t.onLeave,dragover:t.onOver,drop:t.onDrop}},[t._t("default")],2)},kc=[],$c={props:{label:{type:String,default:"Drop to upload"},disabled:{type:Boolean,default:!1}},data:function(){return{files:[],dragging:!1,over:!1}},methods:{cancel:function(){this.reset()},reset:function(){this.dragging=!1,this.over=!1},onDrop:function(t){return!0===this.disabled?this.reset():t.dataTransfer.types?!1===t.dataTransfer.types.includes("Files")?this.reset():(this.$events.$emit("dropzone.drop"),this.files=t.dataTransfer.files,this.$emit("drop",this.files),void this.reset()):this.reset()},onEnter:function(t){!1===this.disabled&&t.dataTransfer.types&&t.dataTransfer.types.includes("Files")&&(this.dragging=!0)},onLeave:function(){this.reset()},onOver:function(t){!1===this.disabled&&t.dataTransfer.types&&t.dataTransfer.types.includes("Files")&&(t.dataTransfer.dropEffect="copy",this.over=!0)}}},_c=$c,yc=(n("414d"),Object(u["a"])(_c,vc,kc,!1,null,null,null)),wc=yc.exports,xc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",t._g({staticClass:"k-empty",attrs:{"data-layout":t.layout}},t.$listeners),[t.icon?n("k-icon",{attrs:{type:t.icon}}):t._e(),n("p",[t._t("default")],2)],1)},Oc=[],Cc={props:{text:String,icon:String,layout:{type:String,default:"list"}}},Sc=Cc,Ec=(n("ba8f"),Object(u["a"])(Sc,xc,Oc,!1,null,null,null)),jc=Ec.exports,Tc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-file-preview"},[n("k-view",{staticClass:"k-file-preview-layout"},[n("div",{staticClass:"k-file-preview-image"},[n("a",{directives:[{name:"tab",rawName:"v-tab"}],staticClass:"k-file-preview-image-link",attrs:{href:t.file.url,title:t.$t("open"),target:"_blank"}},[t.file.panelImage&&t.file.panelImage.cards&&t.file.panelImage.cards.url?n("k-image",{attrs:{src:t.file.panelImage.cards.url,srcset:t.file.panelImage.cards.srcset,back:"none"}}):t.file.panelIcon?n("k-icon",{staticClass:"k-file-preview-icon",style:{color:t.file.panelIcon.color},attrs:{type:t.file.panelIcon.type}}):n("span",{staticClass:"k-file-preview-placeholder"})],1)]),n("div",{staticClass:"k-file-preview-details"},[n("ul",[n("li",[n("h3",[t._v(t._s(t.$t("template")))]),n("p",[t._v(t._s(t.file.template||"—"))])]),n("li",[n("h3",[t._v(t._s(t.$t("mime")))]),n("p",[t._v(t._s(t.file.mime))])]),n("li",[n("h3",[t._v(t._s(t.$t("url")))]),n("p",[n("k-link",{attrs:{to:t.file.url,tabindex:"-1",target:"_blank"}},[t._v("/"+t._s(t.file.id))])],1)]),n("li",[n("h3",[t._v(t._s(t.$t("size")))]),n("p",[t._v(t._s(t.file.niceSize))])]),n("li",[n("h3",[t._v(t._s(t.$t("dimensions")))]),t.file.dimensions?n("p",[t._v(t._s(t.file.dimensions.width)+"×"+t._s(t.file.dimensions.height)+" "+t._s(t.$t("pixel")))]):n("p",[t._v("—")])]),n("li",[n("h3",[t._v(t._s(t.$t("orientation")))]),t.file.dimensions?n("p",[t._v(t._s(t.$t("orientation."+t.file.dimensions.orientation)))]):n("p",[t._v("—")])])])])])],1)},Lc=[],Ic={props:{file:Object}},qc=Ic,Ac=(n("696b5"),Object(u["a"])(qc,Tc,Lc,!1,null,null,null)),Nc=Ac.exports,Bc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-grid",attrs:{"data-gutter":t.gutter}},[t._t("default")],2)},Pc=[],Dc={props:{gutter:String}},Mc=Dc,Rc=(n("5b23"),Object(u["a"])(Mc,Bc,Pc,!1,null,null,null)),zc=Rc.exports,Fc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("header",{staticClass:"k-header",attrs:{"data-editable":t.editable}},[n("k-headline",{attrs:{tag:"h1",size:"huge"}},[t.editable&&t.$listeners.edit?n("span",{staticClass:"k-headline-editable",on:{click:function(e){return t.$emit("edit")}}},[t._t("default"),n("k-icon",{attrs:{type:"edit"}})],2):t._t("default")],2),t.$slots.left||t.$slots.right?n("k-bar",{staticClass:"k-header-buttons"},[t._t("left",null,{slot:"left"}),t._t("right",null,{slot:"right"})],2):t._e(),t.tabs&&t.tabs.length>1?n("div",{staticClass:"k-header-tabs"},[n("nav",[t._l(t.visibleTabs,function(e,i){return n("k-button",{key:t.$route.fullPath+"-tab-"+i,staticClass:"k-tab-button",attrs:{link:"#"+e.name,current:t.currentTab&&t.currentTab.name===e.name,icon:e.icon,tooltip:e.label}},[t._v("\n "+t._s(e.label)+"\n ")])}),t.invisibleTabs.length?n("k-button",{staticClass:"k-tab-button k-tabs-dropdown-button",attrs:{icon:"dots"},on:{click:function(e){return e.stopPropagation(),t.$refs.more.toggle()}}},[t._v("\n "+t._s(t.$t("more"))+"\n ")]):t._e()],2),t.invisibleTabs.length?n("k-dropdown-content",{ref:"more",staticClass:"k-tabs-dropdown",attrs:{align:"right"}},t._l(t.invisibleTabs,function(e,i){return n("k-dropdown-item",{key:"more-"+i,attrs:{link:"#"+e.name,current:t.currentTab&&t.currentTab.name===e.name,icon:e.icon,tooltip:e.label}},[t._v("\n "+t._s(e.label)+"\n ")])}),1):t._e()],1):t._e()],1)},Uc=[],Hc={props:{editable:Boolean,tabs:Array,tab:Object},data:function(){return{size:null,currentTab:this.tab,visibleTabs:this.tabs,invisibleTabs:[]}},watch:{tab:function(){this.currentTab=this.tab},tabs:function(t){this.visibleTabs=t,this.invisibleTabs=[],this.resize(!0)}},created:function(){window.addEventListener("resize",this.resize)},destroyed:function(){window.removeEventListener("resize",this.resize)},methods:{resize:function(t){if(this.tabs&&!(this.tabs.length<=1)){if(this.tabs.length<=3)return this.visibleTabs=this.tabs,void(this.invisibleTabs=[]);if(window.innerWidth>=700){if("large"===this.size&&!t)return;this.visibleTabs=this.tabs,this.invisibleTabs=[],this.size="large"}else{if("small"===this.size&&!t)return;this.visibleTabs=this.tabs.slice(0,2),this.invisibleTabs=this.tabs.slice(2),this.size="small"}}}}},Kc=Hc,Vc=(n("53c5"),Object(u["a"])(Kc,Fc,Uc,!1,null,null,null)),Yc=Vc.exports,Wc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"k-list"},[t._t("default",t._l(t.items,function(e,i){return n("k-list-item",t._g(t._b({key:i},"k-list-item",e,!1),t.$listeners))}))],2)},Gc=[],Jc={props:{items:Array}},Zc=Jc,Xc=(n("c857"),Object(u["a"])(Zc,Wc,Gc,!1,null,null,null)),Qc=Xc.exports,td=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(t.element,t._g({tag:"component",staticClass:"k-list-item"},t.$listeners),[t.sortable?n("k-sort-handle"):t._e(),n("k-link",{directives:[{name:"tab",rawName:"v-tab"}],staticClass:"k-list-item-content",attrs:{to:t.link,target:t.target}},[n("span",{staticClass:"k-list-item-image"},[t.imageOptions?n("k-image",t._b({},"k-image",t.imageOptions,!1)):n("k-icon",t._b({},"k-icon",t.icon,!1))],1),n("span",{staticClass:"k-list-item-text"},[n("em",[t._v(t._s(t.text))]),t.info?n("small",{domProps:{innerHTML:t._s(t.info)}}):t._e()])]),n("nav",{staticClass:"k-list-item-options"},[t._t("options",[t.flag?n("k-button",t._b({on:{click:t.flag.click}},"k-button",t.flag,!1)):t._e(),t.options?n("k-button",{staticClass:"k-list-item-toggle",attrs:{tooltip:t.$t("options"),icon:"dots",alt:"Options"},on:{click:function(e){return e.stopPropagation(),t.$refs.options.toggle()}}}):t._e(),n("k-dropdown-content",{ref:"options",attrs:{options:t.options,align:"right"},on:{action:function(e){return t.$emit("action",e)}}})])],2)],1)},ed=[],nd={inheritAttrs:!1,props:{element:{type:String,default:"li"},image:Object,icon:{type:Object,default:function(){return{type:"file",back:"black"}}},sortable:Boolean,text:String,target:String,info:String,link:String,flag:Object,options:[Array,Function]},computed:{imageOptions:function(){return uu(this.image)}}},id=nd,sd=(n("fa6a"),Object(u["a"])(id,td,ed,!1,null,null,null)),ad=sd.exports,od=function(){var t=this,e=t.$createElement,n=t._self._c||e;return 0===t.tabs.length?n("k-box",{attrs:{text:"This page has no blueprint setup yet",theme:"info"}}):t.tab?n("k-sections",{attrs:{parent:t.parent,blueprint:t.blueprint,columns:t.tab.columns},on:{submit:function(e){return t.$emit("submit",e)}}}):t._e()},rd=[],ld={props:{parent:String,blueprint:String,tabs:Array},data:function(){return{tab:null}},watch:{$route:function(){this.open()},blueprint:function(){this.open()}},mounted:function(){this.open()},methods:{open:function(t){if(0!==this.tabs.length){t||(t=this.$route.hash.replace("#","")),t||(t=this.tabs[0].name);var e=null;this.tabs.forEach(function(n){n.name===t&&(e=n)}),e||(e=this.tabs[0]),this.tab=e,this.$emit("tab",this.tab)}}}},ud=ld,cd=Object(u["a"])(ud,od,rd,!1,null,null,null),dd=cd.exports,pd=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-view",attrs:{"data-align":t.align}},[t._t("default")],2)},fd=[],hd={props:{align:String}},md=hd,gd=(n("daa8"),Object(u["a"])(md,pd,fd,!1,null,null,null)),bd=gd.exports,vd=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("draggable",t._g(t._b({staticClass:"k-draggable",attrs:{tag:t.element,list:t.list,move:t.move}},"draggable",t.dragOptions,!1),t.listeners),[t._t("default"),t._t("footer",null,{slot:"footer"})],2)},kd=[],$d=n("1980"),_d=n.n($d),yd={components:{draggable:_d.a},props:{element:String,handle:[String,Boolean],list:[Array,Object],move:Function,options:Object},data:function(){var t=this;return{listeners:Object(k["a"])({},this.$listeners,{start:function(e){t.$store.dispatch("drag",{}),t.$listeners.start&&t.$listeners.start(e)},end:function(e){t.$store.dispatch("drag",null),t.$listeners.end&&t.$listeners.end(e)}})}},computed:{dragOptions:function(){var t=!1;return t=!0===this.handle?".k-sort-handle":this.handle,Object(k["a"])({fallbackClass:"k-sortable-fallback",fallbackOnBody:!0,forceFallback:!0,ghostClass:"k-sortable-ghost",handle:t,scroll:document.querySelector(".k-panel-view")},this.options)}}},wd=yd,xd=Object(u["a"])(wd,vd,kd,!1,null,null,null),Od=xd.exports,Cd={data:function(){return{error:null}},errorCaptured:function(t){return y.debug&&window.console.warn(t),this.error=t,!1},render:function(t){return this.error?this.$slots.error?this.$slots.error[0]:this.$scopedSlots.error?this.$scopedSlots.error({error:this.error}):t("k-box",{attrs:{theme:"negative"}},this.error.message||this.error):this.$slots.default[0]}},Sd=Cd,Ed=Object(u["a"])(Sd,Fr,Ur,!1,null,null,null),jd=Ed.exports,Td=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(t.tag,t._g({tag:"component",staticClass:"k-headline",attrs:{"data-theme":t.theme,"data-size":t.size}},t.$listeners),[t.link?n("k-link",{attrs:{to:t.link}},[t._t("default")],2):t._t("default")],2)},Ld=[],Id={props:{link:String,size:{type:String},tag:{type:String,default:"h2"},theme:{type:String}}},qd=Id,Ad=(n("f8a7"),Object(u["a"])(qd,Td,Ld,!1,null,null,null)),Nd=Ad.exports,Bd=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{class:"k-icon k-icon-"+t.type,attrs:{"aria-label":t.alt,role:t.alt?"img":null,"aria-hidden":!t.alt,"data-back":t.back,"data-size":t.size}},[t.emoji?n("span",{staticClass:"k-icon-emoji"},[t._v(t._s(t.type))]):n("svg",{style:{color:t.color},attrs:{viewBox:"0 0 16 16"}},[n("use",{attrs:{"xlink:href":"#icon-"+t.type}})])])},Pd=[],Dd={props:{alt:String,color:String,back:String,emoji:Boolean,size:String,type:String}},Md=Dd,Rd=(n("3342"),Object(u["a"])(Md,Bd,Pd,!1,null,null,null)),zd=Rd.exports,Fd=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",t._g({staticClass:"k-image",attrs:{"data-ratio":t.ratio,"data-back":t.back,"data-cover":t.cover}},t.$listeners),[n("span",{style:"padding-bottom:"+t.ratioPadding},[t.loaded?n("img",{key:t.src,attrs:{alt:t.alt||"",src:t.src,srcset:t.srcset,sizes:t.sizes},on:{dragstart:function(t){t.preventDefault()}}}):t._e(),t.loaded||t.error?t._e():n("k-loader",{attrs:{position:"center",theme:"light"}}),!t.loaded&&t.error?n("k-icon",{staticClass:"k-image-error",attrs:{type:"cancel"}}):t._e()],1)])},Ud=[],Hd={props:{alt:String,back:String,cover:Boolean,ratio:String,sizes:String,src:String,srcset:String},data:function(){return{loaded:{type:Boolean,default:!1},error:{type:Boolean,default:!1}}},computed:{ratioPadding:function(){return Gu(this.ratio||"1/1")}},created:function(){var t=this,e=new Image;e.onload=function(){t.loaded=!0,t.$emit("load")},e.onerror=function(){t.error=!0,t.$emit("error")},e.src=this.src}},Kd=Hd,Vd=(n("0d56"),Object(u["a"])(Kd,Fd,Ud,!1,null,null,null)),Yd=Vd.exports,Wd=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("progress",{staticClass:"k-progress",attrs:{max:"100"},domProps:{value:t.state}},[t._v("\n "+t._s(t.state)+"%\n")])},Gd=[],Jd={props:{value:{type:Number,default:0}},data:function(){return{state:this.value}},methods:{set:function(t){this.state=t}}},Zd=Jd,Xd=(n("9799"),Object(u["a"])(Zd,Wd,Gd,!1,null,null,null)),Qd=Xd.exports,tp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{staticClass:"k-sort-handle",attrs:{"aria-hidden":"true"}},[n("svg",{attrs:{viewBox:"0 0 16 16"}},[n("use",{attrs:{"xlink:href":"#icon-sort"}})])])},ep=[],np=(n("35cb"),{}),ip=Object(u["a"])(np,tp,ep,!1,null,null,null),sp=ip.exports,ap=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-text",attrs:{"data-align":t.align,"data-size":t.size,"data-theme":t.theme}},[t._t("default")],2)},op=[],rp={props:{align:String,size:String,theme:String}},lp=rp,up=(n("b0d6"),Object(u["a"])(lp,ap,op,!1,null,null,null)),cp=up.exports,dp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(t.component,t._g({directives:[{name:"tab",rawName:"v-tab"}],ref:"button",tag:"component",staticClass:"k-button",attrs:{"aria-current":t.current,autofocus:t.autofocus,id:t.id,disabled:t.disabled,"data-tabbed":t.tabbed,"data-theme":t.theme,"data-responsive":t.responsive,role:t.role,tabindex:t.tabindex,target:t.target,title:t.tooltip,to:t.link,type:t.link?null:t.type}},t.$listeners),[t.icon?n("k-icon",{staticClass:"k-button-icon",attrs:{type:t.icon,alt:t.tooltip}}):t._e(),t.$slots.default?n("span",{staticClass:"k-button-text"},[t._t("default")],2):t._e()],1)},pp=[],fp={directives:{tab:S},inheritAttrs:!1,props:{autofocus:Boolean,current:[String,Boolean],disabled:Boolean,icon:String,id:[String,Number],link:String,responsive:Boolean,role:String,target:String,tabindex:String,theme:String,tooltip:String,type:{type:String,default:"button"}},data:function(){return{tabbed:!1}},computed:{component:function(){return this.link?"k-link":"button"},imageUrl:function(){return this.image?"object"===Object(zt["a"])(this.image)?this.image.url:this.image:null}},methods:{focus:function(){this.$refs.button.focus()},tab:function(){this.focus(),this.tabbed=!0},untab:function(){this.tabbed=!1}}},hp=fp,mp=(n("3787"),Object(u["a"])(hp,dp,pp,!1,null,null,null)),gp=mp.exports,bp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-button-group"},[t._t("default")],2)},vp=[],kp=(n("a567"),{}),$p=Object(u["a"])(kp,bp,vp,!1,null,null,null),_p=$p.exports,yp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{staticClass:"k-dropdown",on:{click:function(t){t.stopPropagation()}}},[t._t("default")],2)},wp=[],xp=(n("f95f"),{}),Op=Object(u["a"])(xp,yp,wp,!1,null,null,null),Cp=Op.exports,Sp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.isOpen?n("div",{staticClass:"k-dropdown-content",attrs:{"data-align":t.align}},[t._t("default",[t._l(t.items,function(e,i){return["-"===e?n("hr",{key:t._uid+"-item-"+i}):n("k-dropdown-item",t._b({key:t._uid+"-item-"+i,ref:t._uid+"-item-"+i,refInFor:!0,on:{click:function(n){return t.$emit("action",e.click)}}},"k-dropdown-item",e,!1),[t._v("\n "+t._s(e.text)+"\n ")])]})])],2):t._e()},Ep=[],jp=null,Tp={props:{options:[Array,Function],align:String},data:function(){return{items:[],current:-1,isOpen:!1}},methods:{fetchOptions:function(t){if(!this.options)return t(this.items);"string"===typeof this.options?fetch(this.options).then(function(t){return t.json()}).then(function(e){return t(e)}):"function"===typeof this.options?this.options(t):_t()(this.options)&&t(this.options)},open:function(){var t=this;this.reset(),jp&&jp!==this&&jp.close(),this.fetchOptions(function(e){t.$events.$on("keydown",t.navigate),t.$events.$on("click",t.close),t.items=e,t.isOpen=!0,t.$emit("open"),jp=t})},reset:function(){this.current=-1,this.$events.$off("keydown",this.navigate),this.$events.$off("click",this.close)},close:function(){this.reset(),this.isOpen=jp=!1,this.$emit("close")},toggle:function(){this.isOpen?this.close():this.open()},focus:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;this.$children[t]&&this.$children[t].focus&&(this.current=t,this.$children[t].focus())},navigate:function(t){switch(t.code){case"Escape":case"ArrowLeft":this.close(),this.$emit("leave",t.code);break;case"ArrowUp":t.preventDefault();while(1){if(this.current--,this.current<0){this.close(),this.$emit("leave",t.code);break}if(this.$children[this.current]&&!1===this.$children[this.current].disabled){this.focus(this.current);break}}break;case"ArrowDown":t.preventDefault();while(1){if(this.current++,this.current>this.$children.length-1){var e=this.$children.filter(function(t){return!1===t.disabled});this.current=this.$children.indexOf(e[e.length-1]);break}if(this.$children[this.current]&&!1===this.$children[this.current].disabled){this.focus(this.current);break}}break}}}},Lp=Tp,Ip=(n("98a1"),Object(u["a"])(Lp,Sp,Ep,!1,null,null,null)),qp=Ip.exports,Ap=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-button",t._g(t._b({ref:"button",staticClass:"k-dropdown-item"},"k-button",t.$props,!1),t.listeners),[t._t("default")],2)},Np=[],Bp={inheritAttrs:!1,props:{disabled:Boolean,icon:String,image:[String,Object],link:String,target:String,theme:String,upload:String,current:[String,Boolean]},data:function(){var t=this;return{listeners:Object(k["a"])({},this.$listeners,{click:function(e){t.$parent.close(),t.$emit("click",e)}})}},methods:{focus:function(){this.$refs.button.focus()},tab:function(){this.$refs.button.tab()}}},Pp=Bp,Dp=(n("580a"),Object(u["a"])(Pp,Ap,Np,!1,null,null,null)),Mp=Dp.exports,Rp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.to&&!t.disabled?n("a",t._g({ref:"link",staticClass:"k-link",attrs:{href:t.href,rel:t.relAttr,tabindex:t.tabindex,target:t.target,title:t.title}},t.listeners),[t._t("default")],2):n("span",{staticClass:"k-link",attrs:{title:t.title,"data-disabled":""}},[t._t("default")],2)},zp=[],Fp={props:{disabled:Boolean,rel:String,tabindex:[String,Number],target:String,title:String,to:String},data:function(){return{relAttr:"_blank"===this.target?"noreferrer noopener":this.rel,listeners:Object(k["a"])({},this.$listeners,{click:this.onClick})}},computed:{href:function(){return void 0===this.$route||"/"!==this.to[0]||this.target?this.to:(this.$router.options.url||"")+this.to}},methods:{isRoutable:function(t){return void 0!==this.$route&&(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)&&(!t.defaultPrevented&&((void 0===t.button||0===t.button)&&!this.target)))},onClick:function(t){if(!0===this.disabled)return t.preventDefault(),!1;this.isRoutable(t)&&(t.preventDefault(),this.$router.push(this.to)),this.$emit("click",t)},focus:function(){this.$refs.link.focus()}}},Up=Fp,Hp=Object(u["a"])(Up,Rp,zp,!1,null,null,null),Kp=Hp.exports,Vp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.languages.length?n("k-dropdown",[n("k-button",{attrs:{responsive:!0,icon:"globe"},on:{click:function(e){return t.$refs.languages.toggle()}}},[t._v("\n "+t._s(t.language.name)+"\n ")]),t.languages?n("k-dropdown-content",{ref:"languages"},[n("k-dropdown-item",{on:{click:function(e){return t.change(t.defaultLanguage)}}},[t._v(t._s(t.defaultLanguage.name))]),n("hr"),t._l(t.languages,function(e){return n("k-dropdown-item",{key:e.code,on:{click:function(n){return t.change(e)}}},[t._v("\n "+t._s(e.name)+"\n ")])})],2):t._e()],1):t._e()},Yp=[],Wp={computed:{defaultLanguage:function(){return this.$store.state.languages.default},language:function(){return this.$store.state.languages.current},languages:function(){return this.$store.state.languages.all.filter(function(t){return!1===t.default})}},methods:{change:function(t){this.$store.dispatch("languages/current",t),this.$emit("change",t)}}},Gp=Wp,Jp=Object(u["a"])(Gp,Vp,Yp,!1,null,null,null),Zp=Jp.exports,Xp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.show?n("nav",{staticClass:"k-pagination",attrs:{"data-align":t.align}},[t.show?n("k-button",{attrs:{disabled:!t.hasPrev,tooltip:t.prevLabel,icon:"angle-left"},on:{click:t.prev}}):t._e(),t.details?[t.dropdown?[n("k-dropdown",[n("k-button",{staticClass:"k-pagination-details",attrs:{disabled:!t.hasPages},on:{click:function(e){return t.$refs.dropdown.toggle()}}},[t.total>1?[t._v(t._s(t.detailsText))]:t._e(),t._v(t._s(t.total)+"\n ")],2),n("k-dropdown-content",{ref:"dropdown",staticClass:"k-pagination-selector",on:{open:function(e){t.$nextTick(function(){return t.$refs.page.focus()})}}},[n("div",[n("label",{attrs:{for:"k-pagination-input"}},[t._v(t._s(t.pageLabel))]),n("input",{ref:"page",attrs:{id:"k-pagination-input",min:1,max:t.pages,type:"number"},domProps:{value:t.currentPage},on:{keydown:[function(t){t.stopPropagation()},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:t.goTo(e.target.value)}]}}),n("k-button",{attrs:{icon:"angle-up"},on:{click:function(e){return t.goTo(t.$refs.page.value)}}})],1)])],1)]:[n("span",{staticClass:"k-pagination-details"},[t.total>1?[t._v(t._s(t.detailsText))]:t._e(),t._v(t._s(t.total)+"\n ")],2)]]:t._e(),t.show?n("k-button",{attrs:{disabled:!t.hasNext,tooltip:t.nextLabel,icon:"angle-right"},on:{click:t.next}}):t._e()],2):t._e()},Qp=[],tf={props:{align:{type:String,default:"left"},details:{type:Boolean,default:!1},dropdown:{type:Boolean,default:!0},validate:{type:Function,default:function(){return Ye.a.resolve()}},page:{type:Number,default:1},total:{type:Number,default:0},limit:{type:Number,default:10},keys:{type:Boolean,default:!1},pageLabel:{type:String,default:"Page"},prevLabel:{type:String,default:function(){return this.$t("prev")}},nextLabel:{type:String,default:function(){return this.$t("next")}}},data:function(){return{currentPage:this.page}},computed:{show:function(){return this.pages>1},start:function(){return(this.currentPage-1)*this.limit+1},end:function(){var t=this.start-1+this.limit;return t>this.total?this.total:t},detailsText:function(){return 1===this.limit?this.start+" / ":this.start+"-"+this.end+" / "},pages:function(){return Math.ceil(this.total/this.limit)},hasPrev:function(){return this.start>1},hasNext:function(){return this.endthis.limit},offset:function(){return this.start-1}},watch:{page:function(t){this.currentPage=t}},created:function(){!0===this.keys&&window.addEventListener("keydown",this.navigate,!1)},destroyed:function(){window.removeEventListener("keydown",this.navigate,!1)},methods:{goTo:function(t){var e=this;this.validate(t).then(function(){t<1&&(t=1),t>e.pages&&(t=e.pages),e.currentPage=t,e.$refs.dropdown&&e.$refs.dropdown.close(),e.$emit("paginate",{page:gs()(e.currentPage),start:e.start,end:e.end,limit:e.limit,offset:e.offset})}).catch(function(){})},prev:function(){this.goTo(this.currentPage-1)},next:function(){this.goTo(this.currentPage+1)},navigate:function(t){switch(t.code){case"ArrowLeft":this.prev();break;case"ArrowRight":this.next();break}}}},ef=tf,nf=(n("a66d"),Object(u["a"])(ef,Xp,Qp,!1,null,null,null)),sf=nf.exports,af=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-button-group",{staticClass:"k-prev-next"},[n("k-button",t._b({attrs:{icon:"angle-left"}},"k-button",t.prev,!1)),n("k-button",t._b({attrs:{icon:"angle-right"}},"k-button",t.next,!1))],1)},of=[],rf={props:{prev:{type:Object,default:function(){return{disabled:!0,link:"#"}}},next:{type:Object,default:function(){return{disabled:!0,link:"#"}}}}},lf=rf,uf=(n("7a7d"),Object(u["a"])(lf,af,of,!1,null,null,null)),cf=uf.exports,df=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-search",attrs:{role:"search"},on:{click:t.close}},[n("div",{staticClass:"k-search-box",on:{click:function(t){t.stopPropagation()}}},[n("div",{staticClass:"k-search-input"},[n("k-dropdown",{staticClass:"k-search-types"},[n("k-button",{attrs:{icon:t.type.icon},on:{click:function(e){return t.$refs.types.toggle()}}},[t._v(t._s(t.type.label)+":")]),n("k-dropdown-content",{ref:"types"},t._l(t.types,function(e,i){return n("k-dropdown-item",{key:i,attrs:{icon:e.icon},on:{click:function(e){t.currentType=i}}},[t._v("\n "+t._s(e.label)+"\n ")])}),1)],1),n("input",{directives:[{name:"model",rawName:"v-model",value:t.q,expression:"q"}],ref:"input",attrs:{placeholder:t.$t("search")+" …","aria-label":"$t('search')",type:"text"},domProps:{value:t.q},on:{keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"down",40,e.key,["Down","ArrowDown"])?null:(e.preventDefault(),t.down(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"up",38,e.key,["Up","ArrowUp"])?null:(e.preventDefault(),t.up(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"tab",9,e.key,"Tab")?null:(e.preventDefault(),t.tab(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:t.enter(e)},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"esc",27,e.key,["Esc","Escape"])?null:t.close(e)}],input:function(e){e.target.composing||(t.q=e.target.value)}}}),n("k-button",{staticClass:"k-search-close",attrs:{tooltip:t.$t("close"),icon:"cancel"},on:{click:t.close}})],1),n("ul",t._l(t.items,function(e,i){return n("li",{key:e.id,attrs:{"data-selected":t.selected===i},on:{mouseover:function(e){t.selected=i}}},[n("k-link",{attrs:{to:e.link},on:{click:function(e){return t.click(i)}}},[n("strong",[t._v(t._s(e.title))]),n("small",[t._v(t._s(e.info))])])],1)}),0)])])},pf=[],ff=function(t,e){var n=null;return function(){var i=this,s=arguments;clearTimeout(n),n=setTimeout(function(){t.apply(i,s)},e)}},hf={data:function(){return{items:[],q:null,selected:-1,currentType:"pages"}},computed:{type:function(){return this.types[this.currentType]||this.types["pages"]},types:function(){return{pages:{label:this.$t("pages"),icon:"page",endpoint:"site/search"},users:{label:this.$t("users"),icon:"users",endpoint:"users/search"}}}},watch:{q:ff(function(t){this.search(t)},200),currentType:function(){this.search(this.q)}},mounted:function(){var t=this;this.$nextTick(function(){t.$refs.input.focus()})},methods:{open:function(t){t.preventDefault(),this.$store.dispatch("search",!0)},click:function(t){this.selected=t,this.tab()},close:function(){this.$store.dispatch("search",!1)},down:function(){this.selected=0&&this.selected--}}},mf=hf,gf=(n("4cb2"),Object(u["a"])(mf,df,pf,!1,null,null,null)),bf=gf.exports,vf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{ref:"button",staticClass:"k-tag",attrs:{"data-size":t.size,tabindex:"0"},on:{keydown:function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"delete",[8,46],e.key,["Backspace","Delete","Del"])?null:(e.preventDefault(),t.remove(e))}}},[n("span",{staticClass:"k-tag-text"},[t._t("default")],2),t.removable?n("span",{staticClass:"k-tag-toggle",on:{click:t.remove}},[t._v("×")]):t._e()])},kf=[],$f={props:{removable:Boolean,size:String},methods:{remove:function(){this.removable&&this.$emit("remove")},focus:function(){this.$refs.button.focus()}}},_f=$f,yf=(n("021f"),Object(u["a"])(_f,vf,kf,!1,null,null,null)),wf=yf.exports,xf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.user&&t.view?n("div",{staticClass:"k-topbar"},[n("k-view",[n("div",{staticClass:"k-topbar-wrapper"},[n("k-dropdown",{staticClass:"k-topbar-menu"},[n("k-button",{staticClass:"k-topbar-button k-topbar-menu-button",attrs:{tooltip:t.$t("menu"),icon:"bars"},on:{click:function(e){return t.$refs.menu.toggle()}}},[n("k-icon",{attrs:{type:"angle-down"}})],1),n("k-dropdown-content",{ref:"menu",staticClass:"k-topbar-menu"},[n("ul",[t._l(t.views,function(e,i){return e.menu?n("li",{key:"menu-item-"+i,attrs:{"aria-current":t.$store.state.view===i}},[n("k-dropdown-item",{attrs:{disabled:!1===t.$permissions.access[i],icon:e.icon,link:e.link}},[t._v("\n "+t._s(t.menuTitle(e,i))+"\n ")])],1):t._e()}),n("li",[n("hr")]),n("li",{attrs:{"aria-current":"account"===t.$route.meta.view}},[n("k-dropdown-item",{attrs:{icon:"account",link:"/account"}},[t._v("\n "+t._s(t.$t("view.account"))+"\n ")])],1),n("li",[n("hr")]),n("li",[n("k-dropdown-item",{attrs:{icon:"logout",link:"/logout"}},[t._v("\n "+t._s(t.$t("logout"))+"\n ")])],1)],2)])],1),t.view?n("k-link",{directives:[{name:"tab",rawName:"v-tab"}],staticClass:"k-topbar-button k-topbar-view-button",attrs:{to:t.view.link}},[n("k-icon",{attrs:{type:t.view.icon}}),t._v(" "+t._s(t.breadcrumbTitle)+"\n ")],1):t._e(),t.$store.state.breadcrumb.length>1?n("k-dropdown",{staticClass:"k-topbar-breadcrumb-menu"},[n("k-button",{staticClass:"k-topbar-button",on:{click:function(e){return t.$refs.crumb.toggle()}}},[t._v("\n …\n "),n("k-icon",{attrs:{type:"angle-down"}})],1),n("k-dropdown-content",{ref:"crumb"},[n("k-dropdown-item",{attrs:{icon:t.view.icon,link:t.view.link}},[t._v("\n "+t._s(t.$t("view."+t.$store.state.view,t.view.label))+"\n ")]),t._l(t.$store.state.breadcrumb,function(e,i){return n("k-dropdown-item",{key:"crumb-"+i+"-dropdown",attrs:{icon:t.view.icon,link:e.link}},[t._v("\n "+t._s(e.label)+"\n ")])})],2)],1):t._e(),n("nav",{staticClass:"k-topbar-crumbs"},t._l(t.$store.state.breadcrumb,function(e,i){return n("k-link",{directives:[{name:"tab",rawName:"v-tab"}],key:"crumb-"+i,attrs:{to:e.link}},[t._v("\n "+t._s(e.label)+"\n ")])}),1),n("div",{staticClass:"k-topbar-signals"},[n("span",{directives:[{name:"show",rawName:"v-show",value:t.$store.state.isLoading,expression:"$store.state.isLoading"}],staticClass:"k-topbar-loader"},[n("svg",{attrs:{viewBox:"0 0 16 18"}},[n("path",{attrs:{fill:"white",d:"M8,0 L16,4.50265232 L16,13.5112142 L8,18.0138665 L0,13.5112142 L0,4.50265232 L8,0 Z M2.10648757,5.69852516 L2.10648757,12.3153414 L8,15.632396 L13.8935124,12.3153414 L13.8935124,5.69852516 L8,2.38147048 L2.10648757,5.69852516 Z"}})])]),t.notification?[n("k-button",{staticClass:"k-topbar-notification k-topbar-signals-button",attrs:{theme:"positive"},on:{click:function(e){return t.$store.dispatch("notification/close")}}},[t._v("\n "+t._s(t.notification.message)+"\n ")])]:t.unregistered?[n("div",{staticClass:"k-registration"},[n("p",[t._v(t._s(t.$t("license.unregistered")))]),n("k-button",{staticClass:"k-topbar-signals-button",attrs:{responsive:!0,icon:"key"},on:{click:function(e){return t.$emit("register")}}},[t._v("\n "+t._s(t.$t("license.register"))+"\n ")]),n("k-button",{staticClass:"k-topbar-signals-button",attrs:{responsive:!0,link:"https://getkirby.com/buy",target:"_blank",icon:"cart"}},[t._v("\n "+t._s(t.$t("license.buy"))+"\n ")])],1)]:t._e(),n("k-button",{staticClass:"k-topbar-signals-button",attrs:{tooltip:t.$t("search"),icon:"search"},on:{click:function(e){return t.$store.dispatch("search",!0)}}})],2)],1)])],1):t._e()},Of=[],Cf=Object(k["a"])({site:{link:"/site",icon:"page",menu:!0},users:{link:"/users",icon:"users",menu:!0},settings:{link:"/settings",icon:"settings",menu:!0},account:{link:"/account",icon:"users",menu:!1}},window.panel.plugins.views),Sf={computed:{breadcrumbTitle:function(){var t=this.$t("view.".concat(this.$store.state.view),this.view.label);return"site"===this.$store.state.view&&this.$store.state.system.info.title||t},view:function(){return Cf[this.$store.state.view]},views:function(){return Cf},user:function(){return this.$store.state.user.current},notification:function(){return this.$store.state.notification.type&&"error"!==this.$store.state.notification.type?this.$store.state.notification:null},unregistered:function(){return!this.$store.state.system.info.license}},methods:{menuTitle:function(t,e){var n=this.$t("view."+e,t.label);return"site"===e&&this.$store.state.system.info.site||n}}},Ef=Sf,jf=(n("1e3b"),Object(u["a"])(Ef,xf,Of,!1,null,null,null)),Tf=jf.exports,Lf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-grid",{staticClass:"k-sections",attrs:{gutter:"large"}},t._l(t.columns,function(e,i){return n("k-column",{key:t.parent+"-column-"+i,attrs:{width:e.width}},[t._l(e.sections,function(s,a){return t.meetsCondition(s)?[t.exists(s.type)?n("k-"+s.type+"-section",t._b({key:t.parent+"-column-"+i+"-section-"+a+"-"+t.blueprint,tag:"component",class:"k-section k-section-name-"+s.name,attrs:{name:s.name,parent:t.parent,blueprint:t.blueprint,column:e.width},on:{submit:function(e){return t.$emit("submit",e)}}},"component",s,!1)):[n("k-box",{key:t.parent+"-column-"+i+"-section-"+a,attrs:{text:t.$t("error.section.type.invalid",{type:s.type}),theme:"negative"}})]]:t._e()})],2)}),1)},If=[],qf={props:{parent:String,blueprint:String,columns:[Array,Object]},computed:{content:function(){return this.$store.getters["form/values"]()}},methods:{exists:function(t){return I["a"].options.components["k-"+t+"-section"]},meetsCondition:function(t){var e=this;if(!t.when)return!0;var n=!0;return nt()(t.when).forEach(function(i){var s=e.content[i.toLowerCase()],a=t.when[i];s!==a&&(n=!1)}),n}}},Af=qf,Nf=(n("6bcd"),Object(u["a"])(Af,Lf,If,!1,null,null,null)),Bf=Nf.exports,Pf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{staticClass:"k-info-section"},[n("k-headline",{staticClass:"k-info-section-headline"},[t._v(t._s(t.headline))]),n("k-box",{attrs:{theme:t.theme}},[n("k-text",{domProps:{innerHTML:t._s(t.text)}})],1)],1)},Df=[],Mf={props:{blueprint:String,help:String,name:String,parent:String},methods:{load:function(){return this.$api.get(this.parent+"/sections/"+this.name)}}},Rf={mixins:[Mf],data:function(){return{headline:null,issue:null,text:null,theme:null}},created:function(){var t=this;this.load().then(function(e){t.headline=e.options.headline,t.text=e.options.text,t.theme=e.options.theme||"info"}).catch(function(e){t.issue=e})}},zf=Rf,Ff=(n("4333"),Object(u["a"])(zf,Pf,Df,!1,null,null,null)),Uf=Ff.exports,Hf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return!1===t.isLoading?n("section",{staticClass:"k-pages-section"},[n("header",{staticClass:"k-section-header"},[n("k-headline",{attrs:{link:t.options.link}},[t._v("\n "+t._s(t.headline)+" "),t.options.min?n("abbr",{attrs:{title:"This section is required"}},[t._v("*")]):t._e()]),t.add?n("k-button-group",[n("k-button",{attrs:{icon:"add"},on:{click:t.create}},[t._v(t._s(t.$t("add")))])],1):t._e()],1),t.error?[n("k-box",{attrs:{theme:"negative"}},[n("k-text",{attrs:{size:"small"}},[n("strong",[t._v(t._s(t.$t("error.section.notLoaded",{name:t.name}))+":")]),t._v("\n "+t._s(t.error)+"\n ")])],1)]:[t.data.length?n("k-collection",{attrs:{layout:t.options.layout,help:t.help,items:t.data,pagination:t.pagination,sortable:t.options.sortable,size:t.options.size},on:{change:t.sort,paginate:t.paginate,action:t.action}}):[n("k-empty",{attrs:{layout:t.options.layout,icon:"page"},on:{click:t.create}},[t._v("\n "+t._s(t.options.empty||t.$t("pages.empty"))+"\n ")]),n("footer",{staticClass:"k-collection-footer"},[t.help?n("k-text",{staticClass:"k-collection-help",attrs:{theme:"help"},domProps:{innerHTML:t._s(t.help)}}):t._e()],1)],n("k-page-create-dialog",{ref:"create"}),n("k-page-duplicate-dialog",{ref:"duplicate"}),n("k-page-rename-dialog",{ref:"rename",on:{success:t.update}}),n("k-page-url-dialog",{ref:"url",on:{success:t.update}}),n("k-page-status-dialog",{ref:"status",on:{success:t.update}}),n("k-page-template-dialog",{ref:"template",on:{success:t.update}}),n("k-page-remove-dialog",{ref:"remove",on:{success:t.update}})]],2):t._e()},Kf=[],Vf={inheritAttrs:!1,props:{blueprint:String,column:String,parent:String,name:String},data:function(){return{data:[],error:null,isLoading:!1,options:{empty:null,headline:null,help:null,layout:"list",link:null,max:null,min:null,size:null,sortable:null},pagination:{page:null}}},computed:{headline:function(){return this.options.headline||" "},help:function(){return this.options.help},language:function(){return this.$store.state.languages.current},paginationId:function(){return"kirby$pagination$"+this.parent+"/"+this.name}},watch:{language:function(){this.reload()}},methods:{items:function(t){return t},load:function(t){var e=this;t||(this.isLoading=!0),null===this.pagination.page&&(this.pagination.page=localStorage.getItem(this.paginationId)||1),this.$api.get(this.parent+"/sections/"+this.name,{page:this.pagination.page}).then(function(t){e.isLoading=!1,e.options=t.options,e.pagination=t.pagination,e.data=e.items(t.data)}).catch(function(t){e.isLoading=!1,e.error=t.message})},paginate:function(t){localStorage.setItem(this.paginationId,t.page),this.pagination=t,this.reload()},reload:function(){this.load(!0)}}},Yf={mixins:[Vf],computed:{add:function(){return this.options.add&&this.$permissions.pages.create}},created:function(){this.load(),this.$events.$on("page.changeStatus",this.reload)},destroyed:function(){this.$events.$off("page.changeStatus",this.reload)},methods:{create:function(){this.add&&this.$refs.create.open(this.options.link||this.parent,this.parent+"/children/blueprints",this.name)},action:function(t,e){var n=this,i=this.$api.pages.url(t.id,"lock");this.$api.get(i).then(function(i){if(i.locked&&!1===["preview"].includes(e))n.$store.dispatch("notification/error",n.$t("lock.page.isLocked",{email:i.email}));else switch(e){case"duplicate":n.$refs.duplicate.open(t.id);break;case"preview":var s=window.open("","_blank");s.document.write="...",n.$api.pages.preview(t.id).then(function(t){s.location.href=t}).catch(function(t){n.$store.dispatch("notification/error",t)});break;case"rename":n.$refs.rename.open(t.id);break;case"url":n.$refs.url.open(t.id);break;case"status":n.$refs.status.open(t.id);break;case"template":n.$refs.template.open(t.id);break;case"remove":if(n.data.length<=n.options.min){var a=n.options.min>1?"plural":"singular";n.$store.dispatch("notification/error",{message:n.$t("error.section.pages.min."+a,{section:n.options.headline||n.name,min:n.options.min})});break}n.$refs.remove.open(t.id);break;default:throw new Error("Invalid action")}})},items:function(t){var e=this;return t.map(function(t){return t.flag={class:"k-status-flag k-status-flag-"+t.status,tooltip:e.$t("page.status"),icon:!1===t.permissions.changeStatus?"protected":"circle",disabled:!1===t.permissions.changeStatus,click:function(){e.action(t,"status")}},t.options=function(n){e.$api.pages.options(t.id,"list").then(function(t){return n(t)}).catch(function(t){e.$store.dispatch("notification/error",t)})},t.sortable=t.permissions.sort&&e.options.sortable,t.column=e.column,t})},sort:function(t){var e=this,n=null;if(t.added&&(n="added"),t.moved&&(n="moved"),n){var i=t[n].element,s=t[n].newIndex+1+this.pagination.offset;this.$api.pages.status(i.id,"listed",s).then(function(){e.$store.dispatch("notification/success",":)")}).catch(function(t){e.$store.dispatch("notification/error",{message:t.message,details:t.details}),e.reload()})}},update:function(){this.reload(),this.$events.$emit("model.update")}}},Wf=Yf,Gf=Object(u["a"])(Wf,Hf,Kf,!1,null,null,null),Jf=Gf.exports,Zf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return!1===t.isLoading?n("section",{staticClass:"k-files-section"},[n("header",{staticClass:"k-section-header"},[n("k-headline",[t._v("\n "+t._s(t.headline)+" "),t.options.min?n("abbr",{attrs:{title:"This section is required"}},[t._v("*")]):t._e()]),t.add?n("k-button-group",[n("k-button",{attrs:{icon:"upload"},on:{click:t.upload}},[t._v(t._s(t.$t("add")))])],1):t._e()],1),t.error?[n("k-box",{attrs:{theme:"negative"}},[n("k-text",{attrs:{size:"small"}},[n("strong",[t._v(t._s(t.$t("error.section.notLoaded",{name:t.name}))+":")]),t._v("\n "+t._s(t.error)+"\n ")])],1)]:[n("k-dropzone",{attrs:{disabled:!1===t.add},on:{drop:t.drop}},[t.data.length?n("k-collection",{attrs:{help:t.help,items:t.data,layout:t.options.layout,pagination:t.pagination,sortable:t.options.sortable,size:t.options.size},on:{sort:t.sort,paginate:t.paginate,action:t.action}}):[n("k-empty",{attrs:{layout:t.options.layout,icon:"image"},on:{click:function(e){t.add&&t.upload()}}},[t._v("\n "+t._s(t.options.empty||t.$t("files.empty"))+"\n ")]),n("footer",{staticClass:"k-collection-footer"},[t.help?n("k-text",{staticClass:"k-collection-help",attrs:{theme:"help"},domProps:{innerHTML:t._s(t.help)}}):t._e()],1)]],2),n("k-file-rename-dialog",{ref:"rename",on:{success:t.update}}),n("k-file-remove-dialog",{ref:"remove",on:{success:t.update}}),n("k-upload",{ref:"upload",on:{success:t.uploaded,error:t.reload}})]],2):t._e()},Xf=[],Qf={mixins:[Vf],computed:{add:function(){return!(!this.$permissions.files.create||!1===this.options.upload)&&this.options.upload}},created:function(){this.load(),this.$events.$on("model.update",this.reload)},destroyed:function(){this.$events.$off("model.update",this.reload)},methods:{action:function(t,e){var n=this,i=this.$api.files.url(t.parent,t.filename,"lock");this.$api.get(i).then(function(i){if(i.locked&&!1===["download","edit"].includes(e))n.$store.dispatch("notification/error",n.$t("lock.file.isLocked",{email:i.email}));else switch(e){case"edit":n.$router.push(t.link);break;case"download":window.open(t.url);break;case"rename":n.$refs.rename.open(t.parent,t.filename);break;case"replace":n.replace(t);break;case"remove":if(n.data.length<=n.options.min){var s=n.options.min>1?"plural":"singular";n.$store.dispatch("notification/error",{message:n.$t("error.section.files.min."+s,{section:n.options.headline||n.name,min:n.options.min})});break}n.$refs.remove.open(t.parent,t.filename);break}})},drop:function(t){if(!1===this.add)return!1;this.$refs.upload.drop(t,Object(k["a"])({},this.add,{url:y.api+"/"+this.add.api}))},items:function(t){var e=this;return t.map(function(t){return t.options=function(n){e.$api.files.options(t.parent,t.filename,"list").then(function(t){return n(t)}).catch(function(t){e.$store.dispatch("notification/error",t)})},t.sortable=e.options.sortable,t.column=e.column,t})},replace:function(t){this.$refs.upload.open({url:y.api+"/"+this.$api.files.url(t.parent,t.filename),accept:t.mime,multiple:!1})},sort:function(t){var e=this;if(!1===this.options.sortable)return!1;t=t.map(function(t){return t.id}),this.$api.patch(this.parent+"/files/sort",{files:t,index:this.pagination.offset}).then(function(){e.$store.dispatch("notification/success",":)")}).catch(function(t){e.reload(),e.$store.dispatch("notification/error",t.message)})},update:function(){this.$events.$emit("model.update")},upload:function(){if(!1===this.add)return!1;this.$refs.upload.open(Object(k["a"])({},this.add,{url:y.api+"/"+this.add.api}))},uploaded:function(){this.$events.$emit("file.create"),this.$events.$emit("model.update"),this.$store.dispatch("notification/success",":)")}}},th=Qf,eh=Object(u["a"])(th,Zf,Xf,!1,null,null,null),nh=eh.exports,ih=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.isLoading?t._e():n("section",{staticClass:"k-fields-section"},[t.issue?[n("k-headline",{staticClass:"k-fields-issue-headline"},[t._v("Error")]),n("k-box",{attrs:{text:t.issue.message,theme:"negative"}})]:t._e(),n("k-form",{attrs:{fields:t.fields,validate:!0,value:t.values},on:{input:t.input,submit:t.onSubmit}})],2)},sh=[],ah={mixins:[Mf],inheritAttrs:!1,data:function(){return{fields:{},isLoading:!0,issue:null}},computed:{id:function(){return this.$store.state.form.current},language:function(){return this.$store.state.languages.current},values:function(){return this.$store.getters["form/values"](this.id)}},watch:{language:function(){this.fetch()}},created:function(){this.fetch()},methods:{input:function(t,e,n){this.$store.dispatch("form/update",[this.id,n,t[n]])},fetch:function(){var t=this;this.$api.get(this.parent+"/sections/"+this.name).then(function(e){t.fields=e.fields,nt()(t.fields).forEach(function(e){t.fields[e].section=t.name,t.fields[e].endpoints={field:t.parent+"/fields/"+e,section:t.parent+"/sections/"+t.name,model:t.parent}}),t.isLoading=!1}).catch(function(e){t.issue=e,t.isLoading=!1})},onSubmit:function(t){this.$events.$emit("keydown.cmd.s",t)}}},oh=ah,rh=(n("7d5d"),Object(u["a"])(oh,ih,sh,!1,null,null,null)),lh=rh.exports,uh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-error-view",{staticClass:"k-browser-view"},[n("p",[t._v("\n We are really sorry, but your browser does not support\n all features required for the Kirby Panel.\n ")]),!1===t.hasFetchSupport?[n("p",[n("strong",[t._v("Fetch")]),n("br"),t._v("\n We use Javascript's new Fetch API. You can find a list of supported browsers for this feature on\n "),n("strong",[n("a",{attrs:{href:"https://caniuse.com/#feat=fetch"}},[t._v("caniuse.com")])])])]:t._e(),!1===t.hasGridSupport?[n("p",[n("strong",[t._v("CSS Grid")]),n("br"),t._v("\n We use CSS Grids for all our layouts. You can find a list of supported browsers for this feature on\n "),n("strong",[n("a",{attrs:{href:"https://caniuse.com/#feat=css-grid"}},[t._v("caniuse.com")])])])]:t._e()],2)},ch=[],dh={grid:function(){return!(!window.CSS||!window.CSS.supports("display","grid"))},fetch:function(){return void 0!==window.fetch},all:function(){return this.fetch()&&this.grid()}},ph={computed:{hasFetchSupport:function(){return dh.fetch()},hasGridSupport:function(){return dh.grid()}},created:function(){this.$store.dispatch("form/current",null),dh.all()&&this.$router.push("/")}},fh=ph,hh=(n("d6fc"),Object(u["a"])(fh,uh,ch,!1,null,null,null)),mh=hh.exports,gh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-error-boundary",{key:t.plugin,scopedSlots:t._u([{key:"error",fn:function(e){var i=e.error;return n("k-error-view",{},[t._v("\n "+t._s(i.message||i)+"\n ")])}}])},[n("k-"+t.plugin+"-plugin-view",{tag:"component"})],1)},bh=[],vh={props:{plugin:String},beforeRouteEnter:function(t,e,n){n(function(t){t.$store.dispatch("breadcrumb",[]),t.$store.dispatch("form/current",null)})},watch:{plugin:{handler:function(){this.$store.dispatch("view",this.plugin)},immediate:!0}}},kh=vh,$h=Object(u["a"])(kh,gh,bh,!1,null,null,null),_h=$h.exports,yh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-view",{staticClass:"k-error-view"},[n("div",{staticClass:"k-error-view-content"},[n("k-text",[n("p",[n("k-icon",{staticClass:"k-error-view-icon",attrs:{type:"alert"}})],1),n("p",[t._t("default")],2)])],1)])},wh=[],xh=(n("d221"),{}),Oh=Object(u["a"])(xh,yh,wh,!1,null,null,null),Ch=Oh.exports,Sh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):n("div",{staticClass:"k-file-view"},[n("k-file-preview",{attrs:{file:t.file}}),n("k-view",{staticClass:"k-file-content",attrs:{"data-locked":t.isLocked}},[n("k-header",{attrs:{editable:t.permissions.changeName&&!t.isLocked,tabs:t.tabs,tab:t.tab},on:{edit:function(e){return t.action("rename")}}},[t._v("\n\n "+t._s(t.file.filename)+"\n\n "),n("k-button-group",{attrs:{slot:"left"},slot:"left"},[n("k-button",{attrs:{responsive:!0,icon:"open"},on:{click:function(e){return t.action("download")}}},[t._v("\n "+t._s(t.$t("open"))+"\n ")]),n("k-dropdown",[n("k-button",{attrs:{responsive:!0,disabled:t.isLocked,icon:"cog"},on:{click:function(e){return t.$refs.settings.toggle()}}},[t._v("\n "+t._s(t.$t("settings"))+"\n ")]),n("k-dropdown-content",{ref:"settings",attrs:{options:t.options},on:{action:t.action}})],1),n("k-languages-dropdown")],1),t.file.id?n("k-prev-next",{attrs:{slot:"right",prev:t.prev,next:t.next},slot:"right"}):t._e()],1),t.file.id?n("k-tabs",{key:t.tabsKey,ref:"tabs",attrs:{parent:t.$api.files.url(t.path,t.file.filename),tabs:t.tabs,blueprint:t.file.blueprint.name},on:{tab:function(e){t.tab=e}}}):t._e(),n("k-file-rename-dialog",{ref:"rename",on:{success:t.renamed}}),n("k-file-remove-dialog",{ref:"remove",on:{success:t.deleted}}),n("k-upload",{ref:"upload",attrs:{url:t.uploadApi,accept:t.file.mime,multiple:!1},on:{success:t.uploaded}})],1)],1)},Eh=[],jh={computed:{isLocked:function(){return null!==this.$store.getters["form/lock"]}},created:function(){this.fetch(),this.$events.$on("model.reload",this.fetch),this.$events.$on("keydown.left",this.toPrev),this.$events.$on("keydown.right",this.toNext)},destroyed:function(){this.$events.$off("model.reload",this.fetch),this.$events.$off("keydown.left",this.toPrev),this.$events.$off("keydown.right",this.toNext)},methods:{toPrev:function(t){this.prev&&"body"===t.target.localName&&this.$router.push(this.prev.link)},toNext:function(t){this.next&&"body"===t.target.localName&&this.$router.push(this.next.link)}}},Th={mixins:[jh],props:{path:{type:String},filename:{type:String,required:!0}},data:function(){return{name:"",file:{id:null,parent:null,filename:"",url:"",prev:null,next:null,panelIcon:null,panelImage:null,mime:null,content:{}},permissions:{changeName:!1,delete:!1},issue:null,tabs:[],tab:null,options:null}},computed:{uploadApi:function(){return y.api+"/"+this.path+"/files/"+this.filename},prev:function(){if(this.file.prev)return{link:this.$api.files.link(this.path,this.file.prev.filename),tooltip:this.file.prev.filename}},tabsKey:function(){return"file-"+this.file.id+"-tabs"},language:function(){return this.$store.state.languages.current},next:function(){if(this.file.next)return{link:this.$api.files.link(this.path,this.file.next.filename),tooltip:this.file.next.filename}}},watch:{language:function(){this.fetch()},filename:function(){this.fetch()}},methods:{fetch:function(){var t=this;this.$api.files.get(this.path,this.filename,{view:"panel"}).then(function(e){t.file=e,t.file.next=e.nextWithTemplate,t.file.prev=e.prevWithTemplate,t.file.url=e.url,t.name=e.name,t.tabs=e.blueprint.tabs,t.permissions=e.options,t.options=function(e){t.$api.files.options(t.path,t.file.filename).then(function(t){e(t)})},t.$store.dispatch("breadcrumb",t.$api.files.breadcrumb(t.file,t.$route.name)),t.$store.dispatch("title",t.filename),t.$store.dispatch("form/create",{id:"files/"+e.id,api:t.$api.files.link(t.path,t.filename),content:e.content})}).catch(function(e){window.console.error(e),t.issue=e})},action:function(t){switch(t){case"download":window.open(this.file.url);break;case"rename":this.$refs.rename.open(this.path,this.file.filename);break;case"replace":this.$refs.upload.open({url:y.api+"/"+this.$api.files.url(this.path,this.file.filename),accept:this.file.mime});break;case"remove":this.$refs.remove.open(this.path,this.file.filename);break}},deleted:function(){this.path?this.$router.push("/"+this.path):this.$router.push("/site")},renamed:function(t){this.$router.push(this.$api.files.link(this.path,t.filename))},uploaded:function(){this.fetch(),this.$store.dispatch("notification/success",":)")}}},Lh=Th,Ih=Object(u["a"])(Lh,Sh,Eh,!1,null,null,null),qh=Ih.exports,Ah=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.system?n("k-view",{staticClass:"k-installation-view",attrs:{align:"center"}},["install"===t.state?n("form",{on:{submit:function(e){return e.preventDefault(),t.install(e)}}},[n("h1",{staticClass:"k-offscreen"},[t._v(t._s(t.$t("installation")))]),n("k-fieldset",{attrs:{fields:t.fields,novalidate:!0},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}}),n("k-button",{attrs:{type:"submit",icon:"check"}},[t._v(t._s(t.$t("install")))])],1):"completed"===t.state?n("k-text",[n("k-headline",[t._v(t._s(t.$t("installation.completed")))]),n("k-link",{attrs:{to:"/login"}},[t._v(t._s(t.$t("login")))])],1):n("div",[t.system.isInstalled?t._e():n("k-headline",[t._v(t._s(t.$t("installation.issues.headline")))]),n("ul",{staticClass:"k-installation-issues"},[!1===t.system.isInstallable?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.disabled"))}})],1):t._e(),!1===t.requirements.php?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.php"))}})],1):t._e(),!1===t.requirements.server?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.server"))}})],1):t._e(),!1===t.requirements.mbstring?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.mbstring"))}})],1):t._e(),!1===t.requirements.curl?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.curl"))}})],1):t._e(),!1===t.requirements.accounts?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.accounts"))}})],1):t._e(),!1===t.requirements.content?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.content"))}})],1):t._e(),!1===t.requirements.media?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.media"))}})],1):t._e(),!1===t.requirements.sessions?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.sessions"))}})],1):t._e()]),n("k-button",{attrs:{icon:"refresh"},on:{click:t.check}},[n("span",{domProps:{innerHTML:t._s(t.$t("retry"))}})])],1)],1):t._e()},Nh=[],Bh={data:function(){return{user:{name:"",email:"",language:"",password:"",role:"admin"},languages:[],system:null}},computed:{state:function(){return this.system.isOk&&this.system.isInstallable&&!this.system.isInstalled?"install":this.system.isOk&&this.system.isInstallable&&this.system.isInstalled?"completed":void 0},translation:function(){return this.$store.state.translation.current},requirements:function(){return this.system&&this.system.requirements?this.system.requirements:{}},fields:function(){return{name:{label:this.$t("name"),type:"text",icon:"user",autofocus:!0},email:{label:this.$t("email"),type:"email",link:!1,required:!0},password:{label:this.$t("password"),type:"password",placeholder:this.$t("password")+" …",required:!0},language:{label:this.$t("language"),type:"select",options:this.languages,icon:"globe",empty:!1,required:!0}}}},watch:{translation:{handler:function(t){this.user.language=t},immediate:!0},"user.language":function(t){this.$store.dispatch("translation/activate",t)}},created:function(){this.$store.dispatch("form/current",null),this.check()},methods:{install:function(){var t=this;this.$api.system.install(this.user).then(function(e){t.$store.dispatch("user/current",e),t.$store.dispatch("notification/success",t.$t("welcome")+"!"),t.$router.push("/")}).catch(function(e){t.$store.dispatch("notification/error",e)})},check:function(){var t=this;this.$store.dispatch("system/load",!0).then(function(e){!0===e.isInstalled&&e.isReady?t.$router.push("/login"):t.$api.translations.options().then(function(n){t.languages=n,t.system=e,t.$store.dispatch("title",t.$t("view.installation"))})})}}},Ph=Bh,Dh=(n("146c"),Object(u["a"])(Ph,Ah,Nh,!1,null,null,null)),Mh=Dh.exports,Rh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):t.ready?n("k-view",{staticClass:"k-login-view",attrs:{align:"center"}},[n("k-login-form")],1):t._e()},zh=[],Fh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("form",{staticClass:"k-login-form",attrs:{"data-invalid":t.invalid},on:{submit:function(e){return e.preventDefault(),t.login(e)}}},[n("h1",{staticClass:"k-offscreen"},[t._v(t._s(t.$t("login")))]),n("k-fieldset",{attrs:{novalidate:!0,fields:t.fields},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}}),n("div",{staticClass:"k-login-buttons"},[n("span",{staticClass:"k-login-checkbox"},[n("k-checkbox-input",{attrs:{value:t.user.remember,label:t.$t("login.remember")},on:{input:function(e){t.user.remember=e}}})],1),n("k-button",{staticClass:"k-login-button",attrs:{icon:"check",type:"submit"}},[t._v("\n "+t._s(t.$t("login"))+" "),t.isLoading?[t._v("…")]:t._e()],2)],1)],1)},Uh=[],Hh={data:function(){return{invalid:!1,isLoading:!1,user:{email:"",password:"",remember:!1}}},computed:{fields:function(){return{email:{autofocus:!0,label:this.$t("email"),type:"email",required:!0,link:!1},password:{label:this.$t("password"),type:"password",minLength:8,required:!0,autocomplete:"current-password",counter:!1}}}},methods:{login:function(){var t=this;this.invalid=!1,this.isLoading=!0,this.$store.dispatch("user/login",this.user).then(function(){t.$store.dispatch("system/load",!0).then(function(){t.$store.dispatch("notification/success",t.$t("welcome")),t.isLoading=!1})}).catch(function(){t.invalid=!0,t.isLoading=!1})}}},Kh=Hh,Vh=Object(u["a"])(Kh,Fh,Uh,!1,null,null,null),Yh=Vh.exports,Wh={components:{"k-login-form":window.panel.plugins.login||Yh},data:function(){return{ready:!1,issue:null}},created:function(){var t=this;this.$store.dispatch("form/current",null),this.$store.dispatch("system/load").then(function(e){e.isReady||t.$router.push("/installation"),e.user&&e.user.id&&t.$router.push("/"),t.ready=!0,t.$store.dispatch("title",t.$t("login"))}).catch(function(e){t.issue=e})}},Gh=Wh,Jh=(n("24c1"),Object(u["a"])(Gh,Rh,zh,!1,null,null,null)),Zh=Jh.exports,Xh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):n("k-view",{staticClass:"k-page-view",attrs:{"data-locked":t.isLocked}},[n("k-header",{attrs:{tabs:t.tabs,tab:t.tab,editable:t.permissions.changeTitle&&!t.isLocked},on:{edit:function(e){return t.action("rename")}}},[t._v("\n "+t._s(t.page.title)+"\n "),n("k-button-group",{attrs:{slot:"left"},slot:"left"},[t.permissions.preview&&t.page.previewUrl?n("k-button",{attrs:{responsive:!0,link:t.page.previewUrl,target:"_blank",icon:"open"}},[t._v("\n "+t._s(t.$t("open"))+"\n ")]):t._e(),t.status?n("k-button",{class:["k-status-flag","k-status-flag-"+t.page.status],attrs:{disabled:!t.permissions.changeStatus||t.isLocked,icon:!t.permissions.changeStatus||t.isLocked?"protected":"circle",responsive:!0},on:{click:function(e){return t.action("status")}}},[t._v("\n "+t._s(t.status.label)+"\n ")]):t._e(),n("k-dropdown",[n("k-button",{attrs:{responsive:!0,disabled:!0===t.isLocked,icon:"cog"},on:{click:function(e){return t.$refs.settings.toggle()}}},[t._v("\n "+t._s(t.$t("settings"))+"\n ")]),n("k-dropdown-content",{ref:"settings",attrs:{options:t.options},on:{action:t.action}})],1),n("k-languages-dropdown")],1),t.page.id?n("k-prev-next",{attrs:{slot:"right",prev:t.prev,next:t.next},slot:"right"}):t._e()],1),t.page.id?n("k-tabs",{key:t.tabsKey,ref:"tabs",attrs:{parent:t.$api.pages.url(t.page.id),blueprint:t.blueprint,tabs:t.tabs},on:{tab:t.onTab}}):t._e(),n("k-page-rename-dialog",{ref:"rename",on:{success:t.update}}),n("k-page-duplicate-dialog",{ref:"duplicate"}),n("k-page-url-dialog",{ref:"url"}),n("k-page-status-dialog",{ref:"status",on:{success:t.update}}),n("k-page-template-dialog",{ref:"template",on:{success:t.update}}),n("k-page-remove-dialog",{ref:"remove"})],1)},Qh=[],tm={mixins:[jh],props:{path:{type:String,required:!0}},data:function(){return{page:{title:"",id:null,prev:null,next:null,status:null},blueprint:null,preview:!0,permissions:{changeTitle:!1,changeStatus:!1},icon:"page",issue:null,tab:null,tabs:[],options:null}},computed:{language:function(){return this.$store.state.languages.current},next:function(){if(this.page.next)return{link:this.$api.pages.link(this.page.next.id),tooltip:this.page.next.title}},prev:function(){if(this.page.prev)return{link:this.$api.pages.link(this.page.prev.id),tooltip:this.page.prev.title}},status:function(){return null!==this.page.status?this.page.blueprint.status[this.page.status]:null},tabsKey:function(){return"page-"+this.page.id+"-tabs"}},watch:{language:function(){this.fetch()},path:function(){this.fetch()}},created:function(){this.$events.$on("page.changeSlug",this.update)},destroyed:function(){this.$events.$off("page.changeSlug",this.update)},methods:{action:function(t){switch(t){case"duplicate":this.$refs.duplicate.open(this.page.id);break;case"rename":this.$refs.rename.open(this.page.id);break;case"url":this.$refs.url.open(this.page.id);break;case"status":this.$refs.status.open(this.page.id);break;case"template":this.$refs.template.open(this.page.id);break;case"remove":this.$refs.remove.open(this.page.id);break;default:this.$store.dispatch("notification/error",this.$t("notification.notImplemented"));break}},fetch:function(){var t=this;this.$api.pages.get(this.path,{view:"panel"}).then(function(e){t.page=e,t.blueprint=e.blueprint.name,t.permissions=e.options,t.tabs=e.blueprint.tabs,t.options=function(e){t.$api.pages.options(t.page.id).then(function(t){e(t)})},t.$store.dispatch("breadcrumb",t.$api.pages.breadcrumb(e)),t.$store.dispatch("title",t.page.title),t.$store.dispatch("form/create",{id:"pages/"+t.page.id,api:t.$api.pages.link(t.page.id),content:t.page.content})}).catch(function(e){t.issue=e})},onTab:function(t){this.tab=t},update:function(){this.fetch(),this.$emit("model.update")}}},em=tm,nm=(n("202d"),Object(u["a"])(em,Xh,Qh,!1,null,null,null)),im=nm.exports,sm=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-view",{staticClass:"k-settings-view"},[n("k-header",[t._v("\n "+t._s(t.$t("view.settings"))+"\n ")]),n("section",{staticClass:"k-system-info"},[n("header",[n("k-headline",[t._v("Kirby")])],1),n("ul",{staticClass:"k-system-info-box"},[n("li",[n("dl",[n("dt",[t._v(t._s(t.$t("license")))]),n("dd",[t.license?[t._v("\n "+t._s(t.license)+"\n ")]:n("p",[n("strong",{staticClass:"k-system-unregistered"},[t._v(t._s(t.$t("license.unregistered")))])])],2)])]),n("li",[n("dl",[n("dt",[t._v(t._s(t.$t("version")))]),n("dd",[t._v(t._s(t.$store.state.system.info.version))])])])])]),t.multilang?n("section",{staticClass:"k-languages"},[t.languages.length>0?[n("section",{staticClass:"k-languages-section"},[n("header",[n("k-headline",[t._v(t._s(t.$t("languages.default")))])],1),n("k-collection",{attrs:{items:t.defaultLanguage},on:{action:t.action}})],1),n("section",{staticClass:"k-languages-section"},[n("header",[n("k-headline",[t._v(t._s(t.$t("languages.secondary")))]),n("k-button",{attrs:{icon:"add"},on:{click:function(e){return t.$refs.create.open()}}},[t._v(t._s(t.$t("language.create")))])],1),t.translations.length?n("k-collection",{attrs:{items:t.translations},on:{action:t.action}}):n("k-empty",{attrs:{icon:"globe"},on:{click:function(e){return t.$refs.create.open()}}},[t._v(t._s(t.$t("languages.secondary.empty")))])],1)]:0===t.languages.length?[n("header",[n("k-headline",[t._v(t._s(t.$t("languages")))]),n("k-button",{attrs:{icon:"add"},on:{click:function(e){return t.$refs.create.open()}}},[t._v(t._s(t.$t("language.create")))])],1),n("k-empty",{attrs:{icon:"globe"},on:{click:function(e){return t.$refs.create.open()}}},[t._v(t._s(t.$t("languages.empty")))])]:t._e(),n("k-language-create-dialog",{ref:"create",on:{success:t.fetch}}),n("k-language-update-dialog",{ref:"update",on:{success:t.fetch}}),n("k-language-remove-dialog",{ref:"remove",on:{success:t.fetch}})],2):t._e()],1)},am=[],om={data:function(){return{languages:[]}},computed:{defaultLanguage:function(){return this.languages.filter(function(t){return t.default})},multilang:function(){return this.$store.state.system.info.multilang},license:function(){return this.$store.state.system.info.license},translations:function(){return this.languages.filter(function(t){return!1===t.default})}},created:function(){this.$store.dispatch("form/current",null),this.$store.dispatch("title",this.$t("view.settings")),this.$store.dispatch("breadcrumb",[]),this.fetch()},methods:{fetch:function(){var t=this;!1!==this.multilang?this.$api.get("languages").then(function(e){t.languages=e.data.map(function(n){return{id:n.code,default:n.default,icon:{type:"globe",back:"black"},text:n.name,info:n.code,options:[{icon:"edit",text:t.$t("edit"),click:"update"},{icon:"trash",text:t.$t("delete"),disabled:n.default&&1!==e.data.length,click:"remove"}]}})}):this.languages=[]},action:function(t,e){switch(e){case"update":this.$refs.update.open(t.id);break;case"remove":this.$refs.remove.open(t.id);break}}}},rm=om,lm=(n("9bd5"),Object(u["a"])(rm,sm,am,!1,null,null,null)),um=lm.exports,cm=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):n("k-view",{key:"site-view",staticClass:"k-site-view",attrs:{"data-locked":t.isLocked}},[n("k-header",{attrs:{tabs:t.tabs,tab:t.tab,editable:t.permissions.changeTitle&&!t.isLocked},on:{edit:function(e){return t.action("rename")}}},[t._v("\n "+t._s(t.site.title)+"\n "),n("k-button-group",{attrs:{slot:"left"},slot:"left"},[n("k-button",{attrs:{responsive:!0,link:t.site.previewUrl,target:"_blank",icon:"open"}},[t._v("\n "+t._s(t.$t("open"))+"\n ")]),n("k-languages-dropdown")],1)],1),t.site.url?n("k-tabs",{ref:"tabs",attrs:{tabs:t.tabs,blueprint:t.site.blueprint.name,parent:"site"},on:{tab:function(e){t.tab=e}}}):t._e(),n("k-site-rename-dialog",{ref:"rename",on:{success:t.fetch}})],1)},dm=[],pm={data:function(){return{site:{title:null,url:null},issue:null,tab:null,tabs:[],options:null,permissions:{changeTitle:!0}}},computed:{isLocked:function(){return null!==this.$store.getters["form/lock"]},language:function(){return this.$store.state.languages.current}},watch:{language:function(){this.fetch()}},created:function(){this.fetch()},methods:{fetch:function(){var t=this;this.$api.site.get({view:"panel"}).then(function(e){t.site=e,t.tabs=e.blueprint.tabs,t.permissions=e.options,t.options=function(e){t.$api.site.options().then(function(t){e(t)})},t.$store.dispatch("breadcrumb",[]),t.$store.dispatch("title",null),t.$store.dispatch("form/create",{id:"site",api:"site",content:e.content})}).catch(function(e){t.issue=e})},action:function(t){switch(t){case"languages":this.$refs.languages.open();break;case"rename":this.$refs.rename.open();break;default:this.$store.dispatch("notification/error",this.$t("notification.notImplemented"));break}}}},fm=pm,hm=Object(u["a"])(fm,cm,dm,!1,null,null,null),mm=hm.exports,gm=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):n("k-view",{staticClass:"k-users-view"},[n("k-header",[t._v("\n "+t._s(t.$t("view.users"))+"\n "),n("k-button-group",{attrs:{slot:"left"},slot:"left"},[n("k-button",{attrs:{disabled:!1===t.$permissions.users.create,icon:"add"},on:{click:function(e){return t.$refs.create.open()}}},[t._v(t._s(t.$t("user.create")))])],1),n("k-button-group",{attrs:{slot:"right"},slot:"right"},[n("k-dropdown",[n("k-button",{attrs:{responsive:!0,icon:"funnel"},on:{click:function(e){return t.$refs.roles.toggle()}}},[t._v("\n "+t._s(t.$t("role"))+": "+t._s(t.role?t.role.text:t.$t("role.all"))+"\n ")]),n("k-dropdown-content",{ref:"roles",attrs:{align:"right"}},[n("k-dropdown-item",{attrs:{icon:"bolt"},on:{click:function(e){return t.filter(!1)}}},[t._v("\n "+t._s(t.$t("role.all"))+"\n ")]),n("hr"),t._l(t.roles,function(e){return n("k-dropdown-item",{key:e.value,attrs:{icon:"bolt"},on:{click:function(n){return t.filter(e)}}},[t._v("\n "+t._s(e.text)+"\n ")])})],2)],1)],1)],1),t.users.length>0?[n("k-collection",{attrs:{items:t.users,pagination:t.pagination},on:{paginate:t.paginate,action:t.action}})]:0===t.total?[n("k-empty",{attrs:{icon:"users"}},[t._v(t._s(t.$t("role.empty")))])]:t._e(),n("k-user-create-dialog",{ref:"create",on:{success:t.fetch}}),n("k-user-email-dialog",{ref:"email",on:{success:t.fetch}}),n("k-user-language-dialog",{ref:"language",on:{success:t.fetch}}),n("k-user-password-dialog",{ref:"password"}),n("k-user-remove-dialog",{ref:"remove",on:{success:t.fetch}}),n("k-user-rename-dialog",{ref:"rename",on:{success:t.fetch}}),n("k-user-role-dialog",{ref:"role",on:{success:t.fetch}})],2)},bm=[],vm={data:function(){return{page:1,limit:20,total:null,users:[],roles:[],issue:null}},computed:{pagination:function(){return{page:this.page,limit:this.limit,total:this.total}},role:function(){var t=this,e=null;return this.$route.params.role&&this.roles.forEach(function(n){n.value===t.$route.params.role&&(e=n)}),e}},watch:{$route:function(){this.fetch()}},created:function(){var t=this;this.$store.dispatch("form/current",null),this.$api.roles.options().then(function(e){t.roles=e,t.fetch()})},methods:{fetch:function(){var t=this;this.$store.dispatch("title",this.$t("view.users"));var e={paginate:{page:this.page,limit:this.limit},sortBy:"username asc"};this.role&&(e.filterBy=[{field:"role",operator:"==",value:this.role.value}]),this.$api.users.list(e).then(function(e){t.users=e.data.map(function(e){var n={id:e.id,icon:{type:"user",back:"black"},text:e.name||e.email,info:e.role.title,link:"/users/"+e.id,options:function(n){t.$api.users.options(e.id,"list").then(function(t){return n(t)}).catch(function(e){t.$store.dispatch("notification/error",e)})},image:null};return e.avatar&&(n.image={url:e.avatar.url,cover:!0}),n}),t.role?t.$store.dispatch("breadcrumb",[{link:"/users/role/"+t.role.value,label:t.$t("role")+": "+t.role.text}]):t.$store.dispatch("breadcrumb",[]),t.total=e.pagination.total}).catch(function(e){t.issue=e})},paginate:function(t){this.page=t.page,this.limit=t.limit,this.fetch()},action:function(t,e){switch(e){case"edit":this.$router.push("/users/"+t.id);break;case"email":this.$refs.email.open(t.id);break;case"role":this.$refs.role.open(t.id);break;case"rename":this.$refs.rename.open(t.id);break;case"password":this.$refs.password.open(t.id);break;case"language":this.$refs.language.open(t.id);break;case"remove":this.$refs.remove.open(t.id);break}},filter:function(t){!1===t?this.$router.push("/users"):this.$router.push("/users/role/"+t.value),this.$refs.roles.close()}}},km=vm,$m=Object(u["a"])(km,gm,bm,!1,null,null,null),_m=$m.exports,ym=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):t.ready?n("div",{staticClass:"k-user-view",attrs:{"data-locked":t.isLocked}},[n("div",{staticClass:"k-user-profile"},[n("k-view",[t.avatar?[n("k-dropdown",[n("k-button",{staticClass:"k-user-view-image",attrs:{tooltip:t.$t("avatar"),disabled:t.isLocked},on:{click:function(e){return t.$refs.picture.toggle()}}},[t.avatar?n("k-image",{attrs:{cover:!0,src:t.avatar,ratio:"1/1"}}):t._e()],1),n("k-dropdown-content",{ref:"picture"},[n("k-dropdown-item",{attrs:{icon:"upload"},on:{click:function(e){return t.$refs.upload.open()}}},[t._v("\n "+t._s(t.$t("change"))+"\n ")]),n("k-dropdown-item",{attrs:{icon:"trash"},on:{click:function(e){return t.action("picture.delete")}}},[t._v("\n "+t._s(t.$t("delete"))+"\n ")])],1)],1)]:[n("k-button",{staticClass:"k-user-view-image",attrs:{tooltip:t.$t("avatar")},on:{click:function(e){return t.$refs.upload.open()}}},[n("k-icon",{attrs:{type:"user"}})],1)],n("k-button-group",[n("k-button",{attrs:{disabled:!t.permissions.changeEmail||t.isLocked,icon:"email"},on:{click:function(e){return t.action("email")}}},[t._v(t._s(t.$t("email"))+": "+t._s(t.user.email))]),n("k-button",{attrs:{disabled:!t.permissions.changeRole||t.isLocked,icon:"bolt"},on:{click:function(e){return t.action("role")}}},[t._v(t._s(t.$t("role"))+": "+t._s(t.user.role.title))]),n("k-button",{attrs:{disabled:!t.permissions.changeLanguage||t.isLocked,icon:"globe"},on:{click:function(e){return t.action("language")}}},[t._v(t._s(t.$t("language"))+": "+t._s(t.user.language))])],1)],2)],1),n("k-view",[n("k-header",{attrs:{editable:t.permissions.changeName&&!t.isLocked,tabs:t.tabs,tab:t.tab},on:{edit:function(e){return t.action("rename")}}},[t.user.name&&0!==t.user.name.length?[t._v(t._s(t.user.name))]:n("span",{staticClass:"k-user-name-placeholder"},[t._v(t._s(t.$t("name"))+" …")]),n("k-button-group",{attrs:{slot:"left"},slot:"left"},[n("k-dropdown",[n("k-button",{attrs:{disabled:t.isLocked,icon:"cog"},on:{click:function(e){return t.$refs.settings.toggle()}}},[t._v("\n "+t._s(t.$t("settings"))+"\n ")]),n("k-dropdown-content",{ref:"settings",attrs:{options:t.options},on:{action:t.action}})],1),n("k-languages-dropdown")],1),t.user.id&&"User"===t.$route.name?n("k-prev-next",{attrs:{slot:"right",prev:t.prev,next:t.next},slot:"right"}):t._e()],2),t.user&&t.tabs.length?n("k-tabs",{key:t.tabsKey,ref:"tabs",attrs:{parent:"users/"+t.user.id,blueprint:t.user.blueprint.name,tabs:t.tabs},on:{tab:function(e){t.tab=e}}}):t.ready?n("k-box",{attrs:{text:t.$t("user.blueprint",{role:t.user.role.name}),theme:"info"}}):t._e(),n("k-user-email-dialog",{ref:"email",on:{success:t.fetch}}),n("k-user-language-dialog",{ref:"language",on:{success:t.fetch}}),n("k-user-password-dialog",{ref:"password"}),n("k-user-remove-dialog",{ref:"remove"}),n("k-user-rename-dialog",{ref:"rename",on:{success:t.fetch}}),n("k-user-role-dialog",{ref:"role",on:{success:t.fetch}}),n("k-upload",{ref:"upload",attrs:{url:t.uploadApi,multiple:!1,accept:"image/*"},on:{success:t.uploadedAvatar}})],1)],1):t._e()},wm=[],xm={mixins:[jh],props:{id:{type:String,required:!0}},data:function(){return{tab:null,tabs:[],ready:!1,user:{role:{name:null},name:null,language:null,prev:null,next:null},permissions:{changeEmail:!0,changeName:!0,changeLanguage:!0,changeRole:!0},issue:null,avatar:null,options:null}},computed:{language:function(){return this.$store.state.languages.current},next:function(){if(this.user.next)return{link:this.$api.users.link(this.user.next.id),tooltip:this.user.next.name}},prev:function(){if(this.user.prev)return{link:this.$api.users.link(this.user.prev.id),tooltip:this.user.prev.name}},tabsKey:function(){return"user-"+this.user.id+"-tabs"},uploadApi:function(){return y.api+"/users/"+this.user.id+"/avatar"}},watch:{language:function(){this.fetch()},id:function(){this.fetch()}},methods:{action:function(t){var e=this;switch(t){case"email":this.$refs.email.open(this.user.id);break;case"language":this.$refs.language.open(this.user.id);break;case"password":this.$refs.password.open(this.user.id);break;case"picture.delete":this.$api.users.deleteAvatar(this.id).then(function(){e.$store.dispatch("notification/success",":)"),e.avatar=null});break;case"remove":this.$refs.remove.open(this.user.id);break;case"rename":this.$refs.rename.open(this.user.id);break;case"role":this.$refs.role.open(this.user.id);break;default:this.$store.dispatch("notification/error","Not yet implemented")}},fetch:function(){var t=this;this.$api.users.get(this.id,{view:"panel"}).then(function(e){t.user=e,t.tabs=e.blueprint.tabs,t.ready=!0,t.permissions=e.options,t.options=function(e){t.$api.users.options(t.user.id).then(function(t){e(t)})},e.avatar?t.avatar=e.avatar.url:t.avatar=null,"User"===t.$route.name?t.$store.dispatch("breadcrumb",t.$api.users.breadcrumb(e)):t.$store.dispatch("breadcrumb",[]),t.$store.dispatch("title",t.user.name||t.user.email),t.$store.dispatch("form/create",{id:"users/"+e.id,api:t.$api.users.link(e.id),content:e.content})}).catch(function(e){t.issue=e})},uploadedAvatar:function(){this.$store.dispatch("notification/success",":)"),this.fetch()}}},Om=xm,Cm=(n("bd96"),Object(u["a"])(Om,ym,wm,!1,null,null,null)),Sm=Cm.exports;I["a"].component("k-dialog",R),I["a"].component("k-error-dialog",V),I["a"].component("k-file-rename-dialog",mt),I["a"].component("k-file-remove-dialog",X),I["a"].component("k-files-dialog",Ct),I["a"].component("k-language-create-dialog",It),I["a"].component("k-language-remove-dialog",Dt),I["a"].component("k-language-update-dialog",Kt),I["a"].component("k-page-create-dialog",Zt),I["a"].component("k-page-duplicate-dialog",ie),I["a"].component("k-page-rename-dialog",me),I["a"].component("k-page-remove-dialog",ue),I["a"].component("k-page-status-dialog",_e),I["a"].component("k-page-template-dialog",Se),I["a"].component("k-page-url-dialog",qe),I["a"].component("k-pages-dialog",Me),I["a"].component("k-site-rename-dialog",Ue),I["a"].component("k-user-create-dialog",Ze),I["a"].component("k-user-email-dialog",sn),I["a"].component("k-user-language-dialog",cn),I["a"].component("k-user-password-dialog",gn),I["a"].component("k-user-remove-dialog",yn),I["a"].component("k-user-rename-dialog",En),I["a"].component("k-user-role-dialog",An),I["a"].component("k-users-dialog",Rn),I["a"].component("k-calendar",ei),I["a"].component("k-counter",ri),I["a"].component("k-autocomplete",Vn),I["a"].component("k-form",fi),I["a"].component("k-form-buttons",$i),I["a"].component("k-form-indicator",Ci),I["a"].component("k-field",Ii),I["a"].component("k-fieldset",Di),I["a"].component("k-input",Hi),I["a"].component("k-upload",Qi),I["a"].component("k-checkbox-input",os),I["a"].component("k-checkboxes-input",ps),I["a"].component("k-date-input",$s),I["a"].component("k-datetime-input",Cs),I["a"].component("k-email-input",Bs),I["a"].component("k-multiselect-input",Fs),I["a"].component("k-number-input",Ws),I["a"].component("k-password-input",Xs),I["a"].component("k-radio-input",sa),I["a"].component("k-range-input",ca),I["a"].component("k-select-input",ga),I["a"].component("k-tags-input",ya),I["a"].component("k-tel-input",Ca),I["a"].component("k-text-input",Is),I["a"].component("k-textarea-input",Aa),I["a"].component("k-time-input",Ha),I["a"].component("k-toggle-input",Ja),I["a"].component("k-url-input",to),I["a"].component("k-checkboxes-field",oo),I["a"].component("k-date-field",fo),I["a"].component("k-email-field",ko),I["a"].component("k-files-field",Co),I["a"].component("k-headline-field",Io),I["a"].component("k-info-field",Do),I["a"].component("k-line-field",Uo),I["a"].component("k-multiselect-field",Go),I["a"].component("k-number-field",er),I["a"].component("k-pages-field",rr),I["a"].component("k-password-field",fr),I["a"].component("k-radio-field",kr),I["a"].component("k-range-field",Or),I["a"].component("k-select-field",Lr),I["a"].component("k-structure-field",Yr),I["a"].component("k-tags-field",Qr),I["a"].component("k-text-field",dl),I["a"].component("k-textarea-field",bl),I["a"].component("k-tel-field",al),I["a"].component("k-time-field",wl),I["a"].component("k-toggle-field",jl),I["a"].component("k-url-field",Nl),I["a"].component("k-users-field",zl),I["a"].component("k-toolbar",Wl),I["a"].component("k-toolbar-email-dialog",tu),I["a"].component("k-toolbar-link-dialog",ou),I["a"].component("k-email-field-preview",wu),I["a"].component("k-files-field-preview",fu),I["a"].component("k-pages-field-preview",ju),I["a"].component("k-url-field-preview",ku),I["a"].component("k-users-field-preview",Nu),I["a"].component("k-bar",Ru),I["a"].component("k-box",Vu),I["a"].component("k-card",Qu),I["a"].component("k-cards",ac),I["a"].component("k-collection",dc),I["a"].component("k-column",bc),I["a"].component("k-dropzone",wc),I["a"].component("k-empty",jc),I["a"].component("k-file-preview",Nc),I["a"].component("k-grid",zc),I["a"].component("k-header",Yc),I["a"].component("k-list",Qc),I["a"].component("k-list-item",ad),I["a"].component("k-tabs",dd),I["a"].component("k-view",bd),I["a"].component("k-draggable",Od),I["a"].component("k-error-boundary",jd),I["a"].component("k-headline",Nd),I["a"].component("k-icon",zd),I["a"].component("k-image",Yd),I["a"].component("k-progress",Qd),I["a"].component("k-sort-handle",sp),I["a"].component("k-text",cp),I["a"].component("k-button",gp),I["a"].component("k-button-group",_p),I["a"].component("k-dropdown",Cp),I["a"].component("k-dropdown-content",qp),I["a"].component("k-dropdown-item",Mp),I["a"].component("k-languages-dropdown",Zp),I["a"].component("k-link",Kp),I["a"].component("k-pagination",sf),I["a"].component("k-prev-next",cf),I["a"].component("k-search",bf),I["a"].component("k-tag",wf),I["a"].component("k-topbar",Tf),I["a"].component("k-sections",Bf),I["a"].component("k-info-section",Uf),I["a"].component("k-pages-section",Jf),I["a"].component("k-files-section",nh),I["a"].component("k-fields-section",lh),I["a"].component("k-browser-view",mh),I["a"].component("k-custom-view",_h),I["a"].component("k-error-view",Ch),I["a"].component("k-file-view",qh),I["a"].component("k-installation-view",Mh),I["a"].component("k-login-view",Zh),I["a"].component("k-page-view",im),I["a"].component("k-settings-view",um),I["a"].component("k-site-view",mm),I["a"].component("k-users-view",_m),I["a"].component("k-user-view",Sm);var Em={user:function(){return Xm.get("auth")},login:function(t){var e={long:t.remember||!1,email:t.email,password:t.password};return Xm.post("auth/login",e).then(function(t){return t.user})},logout:function(){return Xm.post("auth/logout")}},jm={get:function(t,e,n){return Xm.get(this.url(t,e),n).then(function(t){return!0===_t()(t.content)&&(t.content={}),t})},update:function(t,e,n){return Xm.patch(this.url(t,e),n)},rename:function(t,e,n){return Xm.patch(this.url(t,e,"name"),{name:n})},url:function(t,e,n){var i=t+"/files/"+e;return n&&(i+="/"+n),i},link:function(t,e,n){return"/"+this.url(t,e,n)},delete:function(t,e){return Xm.delete(this.url(t,e))},options:function(t,e,n){return Xm.get(this.url(t,e),{select:"options"}).then(function(t){var e=t.options,i=[];return"list"===n&&i.push({icon:"open",text:I["a"].i18n.translate("open"),click:"download"}),i.push({icon:"title",text:I["a"].i18n.translate("rename"),click:"rename",disabled:!e.changeName}),i.push({icon:"upload",text:I["a"].i18n.translate("replace"),click:"replace",disabled:!e.replace}),i.push({icon:"trash",text:I["a"].i18n.translate("delete"),click:"remove",disabled:!e.delete}),i})},breadcrumb:function(t,e){var n=null,i=[];switch(e){case"UserFile":i.push({label:t.parent.username,link:Xm.users.link(t.parent.id)}),n="users/"+t.parent.id;break;case"SiteFile":n="site";break;case"PageFile":i=t.parents.map(function(t){return{label:t.title,link:Xm.pages.link(t.id)}}),n=Xm.pages.url(t.parent.id);break}return i.push({label:t.filename,link:this.link(n,t.filename)}),i}},Tm={create:function(t,e){return null===t||"/"===t?Xm.post("site/children",e):Xm.post(this.url(t,"children"),e)},duplicate:function(t,e,n){return Xm.post(this.url(t,"duplicate"),{slug:e,children:n.children||!1,files:n.files||!1})},url:function(t,e){var n=null===t?"pages":"pages/"+t.replace(/\//g,"+");return e&&(n+="/"+e),n},link:function(t){return"/"+this.url(t)},get:function(t,e){return Xm.get(this.url(t),e).then(function(t){return!0===_t()(t.content)&&(t.content={}),t})},options:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"view";return Xm.get(this.url(t),{select:"options"}).then(function(t){var n=t.options,i=[];return"list"===e&&(i.push({click:"preview",icon:"open",text:I["a"].i18n.translate("open"),disabled:!1===n.preview}),i.push("-")),i.push({click:"rename",icon:"title",text:I["a"].i18n.translate("rename"),disabled:!n.changeTitle}),i.push({click:"duplicate",icon:"copy",text:I["a"].i18n.translate("duplicate"),disabled:!n.duplicate}),i.push("-"),i.push({click:"url",icon:"url",text:I["a"].i18n.translate("page.changeSlug"),disabled:!n.changeSlug}),i.push({click:"status",icon:"preview",text:I["a"].i18n.translate("page.changeStatus"),disabled:!n.changeStatus}),i.push({click:"template",icon:"template",text:I["a"].i18n.translate("page.changeTemplate"),disabled:!n.changeTemplate}),i.push("-"),i.push({click:"remove",icon:"trash",text:I["a"].i18n.translate("delete"),disabled:!n.delete}),i})},preview:function(t){return this.get(t,{select:"previewUrl"}).then(function(t){return t.previewUrl})},update:function(t,e){return Xm.patch(this.url(t),e)},children:function(t,e){return Xm.post(this.url(t,"children/search"),e)},files:function(t,e){return Xm.post(this.url(t,"files/search"),e)},delete:function(t,e){return Xm.delete(this.url(t),e)},slug:function(t,e){return Xm.patch(this.url(t,"slug"),{slug:e})},title:function(t,e){return Xm.patch(this.url(t,"title"),{title:e})},template:function(t,e){return Xm.patch(this.url(t,"template"),{template:e})},search:function(t,e){return t?Xm.post("pages/"+t.replace("/","+")+"/children/search?select=id,title,hasChildren",e):Xm.post("site/children/search?select=id,title,hasChildren",e)},status:function(t,e,n){return Xm.patch(this.url(t,"status"),{status:e,position:n})},breadcrumb:function(t){var e=this,n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=t.parents.map(function(t){return{label:t.title,link:e.link(t.id)}});return!0===n&&i.push({label:t.title,link:this.link(t.id)}),i}},Lm=n("2f62"),Im=n("768b"),qm={namespaced:!0,state:{models:{},current:null,isDisabled:!1,lock:null,unlock:null},getters:{current:function(t){return t.current},exists:function(t){return function(e){return t.models.hasOwnProperty(e)}},hasChanges:function(t,e){return function(t){return nt()(e.model(t).changes).length>0}},id:function(t,e,n){return function(t){return n.languages.current?t+"/"+n.languages.current.code:t}},isCurrent:function(t){return function(e){return t.current===e}},isDisabled:function(t){return!0===t.isDisabled},lock:function(t){return t.lock},model:function(t,e){return function(n){return e.exists(n)?t.models[n]:{originals:{},values:{},changes:{},api:null}}},originals:function(t,e){return function(t){return Mr(e.model(t).originals)}},values:function(t,e){return function(n){return n=n||t.current,Mr(e.model(n).values)}},unlock:function(t){return t.unlock}},mutations:{CREATE:function(t,e){I["a"].set(t.models,e.id,{api:e.api,originals:Mr(e.content),values:Mr(e.content),changes:{}})},CURRENT:function(t,e){t.current=e},DELETE_CHANGES:function(t,e){I["a"].set(t.models[e],"changes",{}),I["a"].set(t.models[e],"values",Mr(t.models[e].originals)),localStorage.removeItem("kirby$form$"+e)},IS_DISABLED:function(t,e){t.isDisabled=e},LOCK:function(t,e){t.lock=e},MOVE:function(t,e){var n=Mr(t.models[e.old]);I["a"].delete(t.models,e.old),I["a"].set(t.models,e.new,n);var i=localStorage.getItem("kirby$form$"+e.old);localStorage.removeItem("kirby$form$"+e.old),localStorage.setItem("kirby$form$"+e.new,i)},REMOVE:function(t,e){I["a"].delete(t.models,e),localStorage.removeItem("kirby$form$"+e)},SET_ORIGINALS:function(t,e){var n=Object(Im["a"])(e,2),i=n[0],s=n[1];t.models[i].originals=Mr(s)},SET_VALUES:function(t,e){var n=Object(Im["a"])(e,2),i=n[0],s=n[1];t.models[i].values=Mr(s)},UNLOCK:function(t,e){t.unlock=e},UPDATE:function(t,e){var n=Object(Im["a"])(e,3),i=n[0],s=n[1],a=n[2];if(!t.models[i])return!1;a=Mr(a),I["a"].set(t.models[i].values,s,a);var o=Dr()(t.models[i].originals[s]),r=Dr()(a);o===r?I["a"].delete(t.models[i].changes,s):I["a"].set(t.models[i].changes,s,!0),localStorage.setItem("kirby$form$"+i,Dr()({api:t.models[i].api,originals:t.models[i].originals,values:t.models[i].values,changes:t.models[i].changes}))}},actions:{create:function(t,e){t.rootState.languages.current&&t.rootState.languages.current.code&&(e.id=t.getters.id(e.id)),(e.id.startsWith("pages/")||e.id.startsWith("site"))&&delete e.content.title,t.commit("CREATE",e),t.dispatch("current",e.id),t.dispatch("load",e)},current:function(t,e){t.commit("CURRENT",e)},load:function(t,e){var n=localStorage.getItem("kirby$form$"+e.id);if(n){var i=JSON.parse(n);Xm.get(e.api+"/unlock").then(function(n){!1!==n.supported&&!1!==n.unlocked?t.commit("UNLOCK",i.values):nt()(i.values).forEach(function(n){var s=i.values[n];t.commit("UPDATE",[e.id,n,s])})})}},disable:function(t){t.commit("IS_DISABLED",!0)},enable:function(t){t.commit("IS_DISABLED",!1)},lock:function(t,e){t.commit("LOCK",e)},move:function(t,e){t.commit("MOVE",e)},remove:function(t,e){t.commit("REMOVE",e)},revert:function(t,e){var n=t.getters.model(e);return Xm.get(n.api,{select:"content"}).then(function(n){(e.startsWith("pages/")||e.startsWith("site"))&&delete n.content.title,t.commit("SET_ORIGINALS",[e,n.content]),t.commit("SET_VALUES",[e,n.content]),t.commit("DELETE_CHANGES",e)})},save:function(t,e){e=e||t.state.current;var n=t.getters.model(e);return(!t.getters.isCurrent(e)||!t.state.isDisabled)&&(t.dispatch("disable"),Xm.patch(n.api,n.values).then(function(){t.dispatch("revert",e),t.dispatch("enable")}).catch(function(e){throw t.dispatch("enable"),e}))},unlock:function(t,e){t.commit("UNLOCK",e)},update:function(t,e){var n=Object(Im["a"])(e,3),i=n[0],s=n[1],a=n[2];t.commit("UPDATE",[i,s,a])}}},Am={namespaced:!0,state:{instance:null,clock:0,step:5,beats:[]},mutations:{ADD:function(t,e){t.beats.push(e)},CLEAR:function(t){clearInterval(t.instance),t.clock=0},CLOCK:function(t){t.clock+=t.step},INITIALIZE:function(t,e){t.instance=e},REMOVE:function(t,e){var n=t.beats.map(function(t){return t.handler}).indexOf(e);-1!==n&&I["a"].delete(t.beats,n)}},actions:{add:function(t,e){e={handler:e[0]||e,interval:e[1]||t.state.step},e.handler(),t.commit("ADD",e),1===t.state.beats.length&&t.dispatch("run")},clear:function(t){t.commit("CLEAR")},remove:function(t,e){t.commit("REMOVE",e),t.state.beats.length<1&&t.commit("CLEAR")},run:function(t){t.commit("CLEAR"),t.commit("INITIALIZE",setInterval(function(){t.commit("CLOCK"),t.state.beats.forEach(function(e){t.state.clock%e.interval===0&&e.handler()})},1e3*t.state.step))}}},Nm={namespaced:!0,state:{all:[],current:null,default:null},mutations:{SET_ALL:function(t,e){t.all=e.map(function(t){return{code:t.code,name:t.name,default:t.default,direction:t.direction,rules:t.rules}})},SET_CURRENT:function(t,e){t.current=e,e&&e.code&&localStorage.setItem("kirby$language",e.code)},SET_DEFAULT:function(t,e){t.default=e}},actions:{current:function(t,e){t.commit("SET_CURRENT",e)},install:function(t,e){var n=e.filter(function(t){return t.default})[0];t.commit("SET_ALL",e),t.commit("SET_DEFAULT",n);var i=localStorage.getItem("kirby$language");if(i){var s=e.filter(function(t){return t.code===i})[0];if(s)return void t.dispatch("current",s)}t.dispatch("current",n||e[0]||null)},load:function(t){return Xm.get("languages").then(function(e){t.dispatch("install",e.data)})}}},Bm={timer:null,namespaced:!0,state:{type:null,message:null,details:null,timeout:null},mutations:{SET:function(t,e){t.type=e.type,t.message=e.message,t.details=e.details,t.timeout=e.timeout},UNSET:function(t){t.type=null,t.message=null,t.details=null,t.timeout=null}},actions:{close:function(t){clearTimeout(this.timer),t.commit("UNSET")},open:function(t,e){t.dispatch("close"),t.commit("SET",e),e.timeout&&(this.timer=setTimeout(function(){t.dispatch("close")},e.timeout))},success:function(t,e){"string"===typeof e&&(e={message:e}),t.dispatch("open",Object(k["a"])({type:"success",timeout:4e3},e))},error:function(t,e){"string"===typeof e&&(e={message:e}),t.dispatch("open",Object(k["a"])({type:"error"},e))}}},Pm={namespaced:!0,state:{info:{title:null}},mutations:{SET_INFO:function(t,e){t.info=e},SET_LICENSE:function(t,e){t.info.license=e},SET_TITLE:function(t,e){t.info.title=e}},actions:{title:function(t,e){t.commit("SET_TITLE",e)},register:function(t,e){t.commit("SET_LICENSE",e)},load:function(t,e){return!e&&t.state.info.isReady&&t.rootState.user.current?new Ye.a(function(e){e(t.state.info)}):Xm.system.info({view:"panel"}).then(function(e){return t.commit("SET_INFO",Object(k["a"])({isReady:e.isInstalled&&e.isOk},e)),e.languages&&t.dispatch("languages/install",e.languages,{root:!0}),t.dispatch("translation/install",e.translation,{root:!0}),t.dispatch("translation/activate",e.translation.id,{root:!0}),e.user&&t.dispatch("user/current",e.user,{root:!0}),t.state.info}).catch(function(e){t.commit("SET_INFO",{isBroken:!0,error:e.message})})}}},Dm={namespaced:!0,state:{current:null,installed:[]},mutations:{SET_CURRENT:function(t,e){t.current=e},INSTALL:function(t,e){t.installed[e.id]=e}},actions:{load:function(t,e){return Xm.translations.get(e)},install:function(t,e){t.commit("INSTALL",e),I["a"].i18n.add(e.id,e.data)},activate:function(t,e){var n=t.state.installed[e];n?(I["a"].i18n.set(e),t.commit("SET_CURRENT",e),document.dir=n.direction,document.documentElement.lang=e):t.dispatch("load",e).then(function(n){t.dispatch("install",n),t.dispatch("activate",e)})}}},Mm=n("8c4f"),Rm=function(t,e,n){Km.dispatch("system/load").then(function(){var e=Km.state.user.current;if(!e)return Km.dispatch("user/visit",t.path),Km.dispatch("user/logout"),!1;var i=e.permissions.access;return!1===i.panel?(window.location.href=y.site,!1):!1===i[t.meta.view]?(Km.dispatch("notification/error",{message:I["a"].i18n.translate("error.access.view")}),n("/")):void n()})},zm=[{path:"/",name:"Home",redirect:"/site"},{path:"/browser",name:"Browser",component:I["a"].component("k-browser-view"),meta:{outside:!0}},{path:"/login",component:I["a"].component("k-login-view"),meta:{outside:!0}},{path:"/logout",beforeEnter:function(){nt()(localStorage).forEach(function(t){t.startsWith("kirby$form")&&localStorage.removeItem(t)}),Km.dispatch("user/logout")},meta:{outside:!0}},{path:"/installation",component:I["a"].component("k-installation-view"),meta:{outside:!0}},{path:"/site",name:"Site",meta:{view:"site"},component:I["a"].component("k-site-view"),beforeEnter:Rm},{path:"/site/files/:filename",name:"SiteFile",meta:{view:"site"},component:I["a"].component("k-file-view"),beforeEnter:Rm,props:function(t){return{path:"site",filename:t.params.filename}}},{path:"/pages/:path/files/:filename",name:"PageFile",meta:{view:"site"},component:I["a"].component("k-file-view"),beforeEnter:Rm,props:function(t){return{path:"pages/"+t.params.path,filename:t.params.filename}}},{path:"/users/:path/files/:filename",name:"UserFile",meta:{view:"users"},component:I["a"].component("k-file-view"),beforeEnter:Rm,props:function(t){return{path:"users/"+t.params.path,filename:t.params.filename}}},{path:"/pages/:path",name:"Page",meta:{view:"site"},component:I["a"].component("k-page-view"),beforeEnter:Rm,props:function(t){return{path:t.params.path}}},{path:"/settings",name:"Settings",meta:{view:"settings"},component:I["a"].component("k-settings-view"),beforeEnter:Rm},{path:"/users/role/:role",name:"UsersByRole",meta:{view:"users"},component:I["a"].component("k-users-view"),beforeEnter:Rm,props:function(t){return{role:t.params.role}}},{path:"/users",name:"Users",meta:{view:"users"},beforeEnter:Rm,component:I["a"].component("k-users-view")},{path:"/users/:id",name:"User",meta:{view:"users"},component:I["a"].component("k-user-view"),beforeEnter:Rm,props:function(t){return{id:t.params.id}}},{path:"/account",name:"Account",meta:{view:"account"},component:I["a"].component("k-user-view"),beforeEnter:Rm,props:function(){return{id:Km.state.user.current?Km.state.user.current.id:null}}},{path:"/plugins/:id",name:"Plugin",meta:{view:"plugin"},props:function(t){return{plugin:t.params.id}},beforeEnter:Rm,component:I["a"].component("k-custom-view")},{path:"*",name:"NotFound",beforeEnter:function(t,e,n){n("/")}}];I["a"].use(Mm["a"]);var Fm=new Mm["a"]({mode:"history",routes:zm,url:"/"===y.url?"":y.url});Fm.beforeEach(function(t,e,n){"Browser"!==t.name&&!1===dh.all()&&n("/browser"),t.meta.outside||Km.dispatch("user/visit",t.path),Km.dispatch("view",t.meta.view),Km.dispatch("form/lock",null),Km.dispatch("form/unlock",null),Km.dispatch("heartbeat/clear"),n()});var Um=Fm,Hm={namespaced:!0,state:{current:null,path:null},mutations:{SET_CURRENT:function(t,e){t.current=e,e&&e.permissions?(I["a"].prototype.$user=e,I["a"].prototype.$permissions=e.permissions):(I["a"].prototype.$user=null,I["a"].prototype.$permissions=null)},SET_PATH:function(t,e){t.path=e}},actions:{current:function(t,e){t.commit("SET_CURRENT",e)},email:function(t,e){t.commit("SET_CURRENT",Object(k["a"])({},t.state.current,{email:e}))},language:function(t,e){t.dispatch("translation/activate",e,{root:!0}),t.commit("SET_CURRENT",Object(k["a"])({},t.state.current,{language:e}))},load:function(t){return Xm.auth.user().then(function(e){return t.commit("SET_CURRENT",e),e})},login:function(t,e){return Xm.auth.login(e).then(function(e){return t.commit("SET_CURRENT",e),t.dispatch("translation/activate",e.language,{root:!0}),Um.push(t.state.path||"/"),e})},logout:function(t,e){t.commit("SET_CURRENT",null),e?window.location.href=(window.panel.url||"")+"/login":Xm.auth.logout().then(function(){Um.push("/login")}).catch(function(){Um.push("/login")})},name:function(t,e){t.commit("SET_CURRENT",Object(k["a"])({},t.state.current,{name:e}))},visit:function(t,e){t.commit("SET_PATH",e)}}};I["a"].use(Lm["a"]);var Km=new Lm["a"].Store({strict:!1,state:{breadcrumb:[],dialog:null,drag:null,isLoading:!1,search:!1,title:null,view:null},mutations:{SET_BREADCRUMB:function(t,e){t.breadcrumb=e},SET_DIALOG:function(t,e){t.dialog=e},SET_DRAG:function(t,e){t.drag=e},SET_SEARCH:function(t,e){!0===e&&(e={}),t.search=e},SET_TITLE:function(t,e){t.title=e},SET_VIEW:function(t,e){t.view=e},START_LOADING:function(t){t.isLoading=!0},STOP_LOADING:function(t){t.isLoading=!1}},actions:{breadcrumb:function(t,e){t.commit("SET_BREADCRUMB",e)},dialog:function(t,e){t.commit("SET_DIALOG",e)},drag:function(t,e){t.commit("SET_DRAG",e)},isLoading:function(t,e){t.commit(!0===e?"START_LOADING":"STOP_LOADING")},search:function(t,e){t.commit("SET_SEARCH",e)},title:function(t,e){t.commit("SET_TITLE",e),document.title=e||"",t.state.system.info.title&&(document.title+=null!==e?" | "+t.state.system.info.title:t.state.system.info.title)},view:function(t,e){t.commit("SET_VIEW",e)}},modules:{form:qm,heartbeat:Am,languages:Nm,notification:Bm,system:Pm,translation:Dm,user:Hm}}),Vm={running:0,request:function(t,e){var n=this,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];e=Wi()(e||{},{credentials:"same-origin",cache:"no-store",headers:Object(k["a"])({"x-requested-with":"xmlhttprequest","content-type":"application/json"},e.headers)}),Km.state.languages.current&&(e.headers["x-language"]=Km.state.languages.current.code),e.headers["x-csrf"]=window.panel.csrf;var s=t+"/"+Dr()(e);return Xm.config.onStart(s,i),this.running++,fetch(Xm.config.endpoint+"/"+t,e).then(function(t){return t.text()}).then(function(t){try{return JSON.parse(t)}catch(e){throw new Error("The JSON response from the API could not be parsed. Please check your API connection.")}}).then(function(t){if(t.status&&"error"===t.status)throw t;var e=t;return t.data&&t.type&&"model"===t.type&&(e=t.data),n.running--,Xm.config.onComplete(s),Xm.config.onSuccess(t),e}).catch(function(t){throw n.running--,Xm.config.onComplete(s),Xm.config.onError(t),t})},get:function(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return e&&(t+="?"+nt()(e).map(function(t){var n=e[t];return void 0!==n&&null!==n?t+"="+n:null}).filter(function(t){return null!==t}).join("&")),this.request(t,Wi()(n||{},{method:"GET"}),i)},post:function(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"POST",s=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return this.request(t,Wi()(n||{},{method:i,body:Dr()(e)}),s)},patch:function(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return this.post(t,e,n,"PATCH",i)},delete:function(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return this.post(t,e,n,"DELETE",i)}},Ym={list:function(t){return Xm.get("roles",t)},get:function(t){return Xm.get("roles/"+t)},options:function(t){return this.list(t).then(function(t){return t.data.map(function(t){return{info:t.description||"(".concat(I["a"].i18n.translate("role.description.placeholder"),")"),text:t.title,value:t.name}})})}},Wm={info:function(t){return Xm.get("system",t)},install:function(t){return Xm.post("system/install",t).then(function(t){return t.user})},register:function(t){return Xm.post("system/register",t)}},Gm={get:function(t){return Xm.get("site",t)},update:function(t){return Xm.post("site",t)},title:function(t){return Xm.patch("site/title",{title:t})},options:function(){return Xm.get("site",{select:"options"}).then(function(t){var e=t.options,n=[];return n.push({click:"rename",icon:"title",text:I["a"].i18n.translate("rename"),disabled:!e.changeTitle}),n})},children:function(t){return Xm.post("site/children/search",t)},blueprint:function(){return Xm.get("site/blueprint")},blueprints:function(){return Xm.get("site/blueprints")}},Jm={list:function(){return Xm.get("translations")},get:function(t){return Xm.get("translations/"+t)},options:function(){var t=[];return this.list().then(function(e){return t=e.data.map(function(t){return{value:t.id,text:t.name}}),t})}},Zm={create:function(t){return Xm.post(this.url(),t)},list:function(t){return Xm.post(this.url(null,"search"),t)},get:function(t,e){return Xm.get(this.url(t),e)},update:function(t,e){return Xm.patch(this.url(t),e)},delete:function(t){return Xm.delete(this.url(t))},changeEmail:function(t,e){return Xm.patch(this.url(t,"email"),{email:e})},changeLanguage:function(t,e){return Xm.patch(this.url(t,"language"),{language:e})},changeName:function(t,e){return Xm.patch(this.url(t,"name"),{name:e})},changePassword:function(t,e){return Xm.patch(this.url(t,"password"),{password:e})},changeRole:function(t,e){return Xm.patch(this.url(t,"role"),{role:e})},deleteAvatar:function(t){return Xm.delete(this.url(t,"avatar"))},blueprint:function(t){return Xm.get(this.url(t,"blueprint"))},breadcrumb:function(t){return[{link:"/users/"+t.id,label:t.username}]},options:function(t){return Xm.get(this.url(t),{select:"options"}).then(function(t){var e=t.options,n=[];return n.push({click:"rename",icon:"title",text:I["a"].i18n.translate("user.changeName"),disabled:!e.changeName}),n.push({click:"email",icon:"email",text:I["a"].i18n.translate("user.changeEmail"),disabled:!e.changeEmail}),n.push({click:"role",icon:"bolt",text:I["a"].i18n.translate("user.changeRole"),disabled:!e.changeRole}),n.push({click:"password",icon:"key",text:I["a"].i18n.translate("user.changePassword"),disabled:!e.changePassword}),n.push({click:"language",icon:"globe",text:I["a"].i18n.translate("user.changeLanguage"),disabled:!e.changeLanguage}),n.push({click:"remove",icon:"trash",text:I["a"].i18n.translate("user.delete"),disabled:!e.delete}),n})},url:function(t,e){var n=t?"users/"+t:"users";return e&&(n+="/"+e),n},link:function(t,e){return"/"+this.url(t,e)}},Xm=Object(k["a"])({config:{onStart:function(){},onComplete:function(){},onSuccess:function(){},onError:function(t){throw window.console.log(t.message),t}},auth:Em,files:jm,pages:Tm,roles:Ym,system:Wm,site:Gm,translations:Jm,users:Zm},Vm);Xm.config.endpoint=y.api,Xm.requests=[],Xm.config.onStart=function(t,e){!1===e&&Km.dispatch("isLoading",!0),Xm.requests.push(t)},Xm.config.onComplete=function(t){Xm.requests=Xm.requests.filter(function(e){return e!==t}),0===Xm.requests.length&&Km.dispatch("isLoading",!1)},Xm.config.onError=function(t){y.debug&&window.console.error(t),403!==t.code||"Unauthenticated"!==t.message&&"access.panel"!==t.key||Km.dispatch("user/logout",!0)};var Qm=setInterval(Xm.auth.user,3e5);Xm.config.onSuccess=function(){clearInterval(Qm),Qm=setInterval(Xm.auth.user,3e5)},I["a"].prototype.$api=Xm,I["a"].config.errorHandler=function(t){y.debug&&window.console.error(t),Km.dispatch("notification/error",{message:t.message||"An error occurred. Please reload the panel"})},window.panel=window.panel||{},window.panel.error=function(t,e){y.debug&&window.console.error(t+": "+e),Km.dispatch("error",t+". See the console for more information.")};var tg=n("f2f3");I["a"].use(tg["a"].plugin,Km);var eg=n("2d1f"),ng=n.n(eg),ig={};for(var sg in I["a"].options.components)ig[sg]=I["a"].options.components[sg];var ag=function(t,e){e.template||e.render||e.extends?(e.extends&&"string"===typeof e.extends&&(e.extends=ig[e.extends],e.template&&(e.render=null)),e.mixins&&(e.mixins=e.mixins.map(function(t){return"string"===typeof t?ig[t]:t})),ig[t]&&window.console.warn('Plugin is replacing "'.concat(t,'"')),I["a"].component(t,e)):Km.dispatch("notification/error",'Neither template or render method provided nor extending a component when loading plugin component "'.concat(t,'". The component has not been registered.'))};ng()(window.panel.plugins.components).forEach(function(t){var e=Object(Im["a"])(t,2),n=e[0],i=e[1];ag(n,i)}),ng()(window.panel.plugins.fields).forEach(function(t){var e=Object(Im["a"])(t,2),n=e[0],i=e[1];ag(n,i)}),ng()(window.panel.plugins.sections).forEach(function(t){var e=Object(Im["a"])(t,2),n=e[0],i=e[1];ag(n,Object(k["a"])({},i,{mixins:[Mf].concat(i.mixins||[])}))}),ng()(window.panel.plugins.views).forEach(function(t){var e=Object(Im["a"])(t,2),n=e[0],i=e[1];if(!i.component)return Km.dispatch("notification/error",'No view component provided when loading view "'.concat(n,'". The view has not been registered.')),void delete window.panel.plugins.views[n];i.link="/plugins/"+n,void 0===i.icon&&(i.icon="page"),void 0===i.menu&&(i.menu=!0),window.panel.plugins.views[n]={link:i.link,icon:i.icon,menu:i.menu},I["a"].component("k-"+n+"-plugin-view",i.component)}),window.panel.plugins.use.forEach(function(t){I["a"].use(t)}),I["a"].use(E),I["a"].use(L),I["a"].use(j),I["a"].use(A.a),I["a"].config.productionTip=!1,I["a"].config.devtools=!0,new I["a"]({router:Um,store:Km,created:function(){var t=this;window.panel.app=this,window.panel.plugins.created.forEach(function(e){e(t)})},render:function(t){return t(C)}}).$mount("#app")},5714:function(t,e,n){},"580a":function(t,e,n){"use strict";var i=n("61ab"),s=n.n(i);s.a},"589a":function(t,e,n){},"58e5":function(t,e,n){},"5ab5":function(t,e,n){},"5aee":function(t,e,n){"use strict";var i=n("04b2"),s=n.n(i);s.a},"5b23":function(t,e,n){"use strict";var i=n("9798"),s=n.n(i);s.a},"5c0b":function(t,e,n){"use strict";var i=n("5e27"),s=n.n(i);s.a},"5d33":function(t,e,n){"use strict";var i=n("2246"),s=n.n(i);s.a},"5e27":function(t,e,n){},"5f12":function(t,e,n){},6018:function(t,e,n){"use strict";var i=n("e30b"),s=n.n(i);s.a},"61ab":function(t,e,n){},"64e6":function(t,e,n){},"65a9":function(t,e,n){},"696b5":function(t,e,n){"use strict";var i=n("0cdc"),s=n.n(i);s.a},"6a18":function(t,e,n){"use strict";var i=n("de8a"),s=n.n(i);s.a},"6ab3":function(t,e,n){"use strict";var i=n("784e"),s=n.n(i);s.a},"6ab9":function(t,e,n){},"6b7f":function(t,e,n){},"6bcd":function(t,e,n){"use strict";var i=n("9e0a"),s=n.n(i);s.a},"6f7b":function(t,e,n){"use strict";var i=n("5ab5"),s=n.n(i);s.a},7075:function(t,e,n){},"718c":function(t,e,n){"use strict";var i=n("773d"),s=n.n(i);s.a},7568:function(t,e,n){"use strict";var i=n("4150"),s=n.n(i);s.a},"75cd":function(t,e,n){},7737:function(t,e,n){"use strict";var i=n("ca19"),s=n.n(i);s.a},"773d":function(t,e,n){},"778b":function(t,e,n){},7797:function(t,e,n){},"784e":function(t,e,n){},"7a7d":function(t,e,n){"use strict";var i=n("65a9"),s=n.n(i);s.a},"7d2d":function(t,e,n){},"7d5d":function(t,e,n){"use strict";var i=n("6ab9"),s=n.n(i);s.a},"7dc7":function(t,e,n){"use strict";var i=n("eb17"),s=n.n(i);s.a},"7e0c":function(t,e,n){},"7e85":function(t,e,n){"use strict";var i=n("d1c5"),s=n.n(i);s.a},"7f6e":function(t,e,n){"use strict";var i=n("4364"),s=n.n(i);s.a},"862b":function(t,e,n){"use strict";var i=n("589a"),s=n.n(i);s.a},"893d":function(t,e,n){"use strict";var i=n("abb3"),s=n.n(i);s.a},"8ae6":function(t,e,n){},"8c28":function(t,e,n){"use strict";var i=n("3d5b"),s=n.n(i);s.a},"8e4d":function(t,e,n){},"910b":function(t,e,n){},"957b":function(t,e,n){},9749:function(t,e,n){},"977f":function(t,e,n){"use strict";var i=n("b7f5"),s=n.n(i);s.a},9798:function(t,e,n){},9799:function(t,e,n){"use strict";var i=n("4fe0"),s=n.n(i);s.a},9811:function(t,e,n){},"98a1":function(t,e,n){"use strict";var i=n("f0cb"),s=n.n(i);s.a},"9bd5":function(t,e,n){"use strict";var i=n("64e6"),s=n.n(i);s.a},"9df7":function(t,e,n){},"9e0a":function(t,e,n){},"9e26":function(t,e,n){"use strict";var i=n("a440"),s=n.n(i);s.a},a134:function(t,e,n){"use strict";var i=n("4390"),s=n.n(i);s.a},a440:function(t,e,n){},a567:function(t,e,n){"use strict";var i=n("c0b5"),s=n.n(i);s.a},a5f3:function(t,e,n){"use strict";var i=n("43f4"),s=n.n(i);s.a},a66d:function(t,e,n){"use strict";var i=n("2eb5"),s=n.n(i);s.a},abb3:function(t,e,n){},ac27:function(t,e,n){"use strict";var i=n("3c9d"),s=n.n(i);s.a},b0d6:function(t,e,n){"use strict";var i=n("d31d"),s=n.n(i);s.a},b37e:function(t,e,n){},b3c3:function(t,e,n){},b5d2:function(t,e,n){"use strict";var i=n("ed7b"),s=n.n(i);s.a},b746:function(t,e,n){"use strict";var i=n("7e0c"),s=n.n(i);s.a},b7f5:function(t,e,n){},ba8f:function(t,e,n){"use strict";var i=n("9749"),s=n.n(i);s.a},bb41:function(t,e,n){"use strict";var i=n("ceb4"),s=n.n(i);s.a},bd96:function(t,e,n){"use strict";var i=n("d6a4"),s=n.n(i);s.a},bf53:function(t,e,n){"use strict";var i=n("3c80"),s=n.n(i);s.a},c0b5:function(t,e,n){},c119:function(t,e,n){"use strict";var i=n("4b49"),s=n.n(i);s.a},c7c8:function(t,e,n){"use strict";var i=n("1be2"),s=n.n(i);s.a},c857:function(t,e,n){"use strict";var i=n("7d2d"),s=n.n(i);s.a},c9cb:function(t,e,n){"use strict";var i=n("b37e"),s=n.n(i);s.a},ca19:function(t,e,n){},ca3a:function(t,e,n){},cb8f:function(t,e,n){"use strict";var i=n("8e4d"),s=n.n(i);s.a},cca8:function(t,e,n){"use strict";var i=n("18b7"),s=n.n(i);s.a},ceb4:function(t,e,n){},d0c1:function(t,e,n){"use strict";var i=n("9df7"),s=n.n(i);s.a},d0e7:function(t,e,n){},d1c5:function(t,e,n){},d221:function(t,e,n){"use strict";var i=n("6b7f"),s=n.n(i);s.a},d31d:function(t,e,n){},d6a4:function(t,e,n){},d6c1:function(t,e,n){},d6fc:function(t,e,n){"use strict";var i=n("08ec"),s=n.n(i);s.a},d9c4:function(t,e,n){},daa8:function(t,e,n){"use strict";var i=n("e60b"),s=n.n(i);s.a},db92:function(t,e,n){},ddfd:function(t,e,n){"use strict";var i=n("4dc8"),s=n.n(i);s.a},de8a:function(t,e,n){},df0d:function(t,e,n){"use strict";var i=n("3ab9"),s=n.n(i);s.a},e30b:function(t,e,n){},e60b:function(t,e,n){},e697:function(t,e,n){},eb17:function(t,e,n){},ec72:function(t,e,n){},ed7b:function(t,e,n){},ee15:function(t,e,n){"use strict";var i=n("fd81"),s=n.n(i);s.a},f0cb:function(t,e,n){},f56d:function(t,e,n){"use strict";var i=n("75cd"),s=n.n(i);s.a},f5e3:function(t,e,n){},f8a7:function(t,e,n){"use strict";var i=n("db92"),s=n.n(i);s.a},f95f:function(t,e,n){"use strict";var i=n("5f12"),s=n.n(i);s.a},fa6a:function(t,e,n){"use strict";var i=n("778b"),s=n.n(i);s.a},fb1a:function(t,e,n){},fc0f:function(t,e,n){"use strict";var i=n("424a"),s=n.n(i);s.a},fd81:function(t,e,n){},ff6d:function(t,e,n){},fffc:function(t,e,n){}});
\ No newline at end of file
+(function(t){function e(e){for(var i,o,r=e[0],l=e[1],u=e[2],d=0,p=[];d0?e.$store.dispatch("notification/error",{message:e.$t("error.page.changeStatus.incomplete"),details:n.errors}):void("default"===n.blueprint.num?e.$api.pages.get(t,{select:["siblings"]}).then(function(t){e.setup(Object(I["a"])({},n,{siblings:t.siblings}))}).catch(function(t){e.$store.dispatch("notification/error",t)}):e.setup(Object(I["a"])({},n,{siblings:[]})))}).catch(function(t){e.$store.dispatch("notification/error",t)})},setup:function(t){this.page=t,this.form.position=t.num||t.siblings.length+1,this.form.status=t.status,this.states=t.blueprint.status,this.$refs.dialog.open()},submit:function(){this.$refs.form.submit()},changeStatus:function(){var t=this;this.$api.pages.status(this.page.id,this.form.status,this.form.position||1).then(function(){t.success({message:":)",event:"page.changeStatus"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},ye=_e,xe=Object(_["a"])(ye,ke,$e,!1,null,null,null),we=xe.exports,Oe=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.page,callback:function(e){t.page=e},expression:"page"}})],1)},Ce=[],Se={mixins:[C],data:function(){return{blueprints:[],page:{id:null,template:null}}},computed:{fields:function(){return{template:{label:this.$t("template"),type:"select",required:!0,empty:!1,options:this.page.blueprints,icon:"template"}}}},methods:{open:function(t){var e=this;this.$api.pages.get(t,{select:["id","template","blueprints"]}).then(function(t){if(t.blueprints.length<=1)return e.$store.dispatch("notification/error",{message:e.$t("error.page.changeTemplate.invalid",{slug:t.id})});e.page=t,e.page.blueprints=e.page.blueprints.map(function(t){return{text:t.title,value:t.name}}),e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$events.$emit("keydown.cmd.s"),this.$api.pages.template(this.page.id,this.page.template).then(function(){t.success({message:":)",event:"page.changeTemplate"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},Ee=Se,je=Object(_["a"])(Ee,Oe,Ce,!1,null,null,null),Te=je.exports,Ie=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",on:{submit:t.submit}},[n("k-text-field",t._b({attrs:{value:t.slug},on:{input:function(e){return t.sluggify(e)}}},"k-text-field",t.field,!1),[n("k-button",{attrs:{slot:"options",icon:"wand","data-options":""},on:{click:function(e){return t.sluggify(t.page.title)}},slot:"options"},[t._v("\n "+t._s(t.$t("page.changeSlug.fromTitle"))+"\n ")])],1)],1)],1)},Le=[],qe={mixins:[C],data:function(){return{slug:null,url:null,page:{id:null,parent:null,title:null}}},computed:{field:function(){return{name:"slug",label:this.$t("slug"),type:"text",required:!0,icon:"url",help:"/"+this.url,counter:!1,preselect:!0}},slugs:function(){return this.$store.state.languages.current?this.$store.state.languages.current.rules:this.system.slugs},system:function(){return this.$store.state.system.info}},methods:{sluggify:function(t){this.slug=this.$helper.slug(t,[this.slugs,this.system.ascii]),this.page.parents?this.url=this.page.parents.map(function(t){return t.slug}).concat([this.slug]).join("/"):this.url=this.slug},open:function(t){var e=this;this.$api.pages.get(t,{view:"panel"}).then(function(t){e.page=t,e.sluggify(e.page.slug),e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;if(this.slug===this.page.slug)return this.$refs.dialog.close(),void this.$store.dispatch("notification/success",":)");0!==this.slug.length?this.$api.pages.slug(this.page.id,this.slug).then(function(e){t.$store.dispatch("content/move",["pages/"+t.page.id,"pages/"+e.id]);var n={message:":)",event:"page.changeSlug"};!t.$route.params.path||t.page.id!==t.$route.params.path.replace(/\+/g,"/")||t.$store.state.languages.current&&!0!==t.$store.state.languages.current.default||(n.route=t.$api.pages.link(e.id),delete n.event),t.success(n)}).catch(function(e){t.$refs.dialog.error(e.message)}):this.$refs.dialog.error(this.$t("error.page.slug.invalid"))}}},Ae=qe,Ne=Object(_["a"])(Ae,Ie,Le,!1,null,null,null),Be=Ne.exports,Pe=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",staticClass:"k-pages-dialog",attrs:{size:"medium"},on:{cancel:function(e){return t.$emit("cancel")},submit:t.submit}},[t.issue?[n("k-box",{attrs:{text:t.issue,theme:"negative"}})]:[t.model?n("header",{staticClass:"k-pages-dialog-navbar"},[n("k-button",{attrs:{disabled:!t.model.id,tooltip:t.$t("back"),icon:"angle-left"},on:{click:t.back}}),n("k-headline",[t._v(t._s(t.model.title))])],1):t._e(),t.options.search?n("k-input",{staticClass:"k-dialog-search",attrs:{autofocus:!0,placeholder:t.$t("search")+" …",type:"text",icon:"search"},model:{value:t.search,callback:function(e){t.search=e},expression:"search"}}):t._e(),t.models.length?[n("k-list",t._l(t.models,function(e){return n("k-list-item",{key:e.id,attrs:{text:e.text,info:e.info,image:e.image,icon:e.icon},on:{click:function(n){return t.toggle(e)}}},[n("template",{slot:"options"},[t.isSelected(e)?n("k-button",{attrs:{slot:"options",autofocus:!0,icon:t.checkedIcon,tooltip:t.$t("remove"),theme:"positive"},slot:"options"}):n("k-button",{attrs:{slot:"options",autofocus:!0,tooltip:t.$t("select"),icon:"circle-outline"},slot:"options"}),t.model?n("k-button",{attrs:{disabled:!e.hasChildren,tooltip:t.$t("open"),icon:"angle-right"},on:{click:function(n){return n.stopPropagation(),t.go(e)}}}):t._e()],1)],2)}),1),n("k-pagination",t._b({staticClass:"k-dialog-pagination",attrs:{details:!0,dropdown:!1,align:"center"},on:{paginate:t.paginate}},"k-pagination",t.pagination,!1))]:n("k-empty",{attrs:{icon:"page"}},[t._v("\n "+t._s(t.$t("dialog.pages.empty"))+"\n ")])]],2)},De=[],Re={mixins:[Ot],data:function(){var t=Ot.data();return Object(I["a"])({},t,{model:{title:null,parent:null},options:Object(I["a"])({},t.options,{parent:null})})},computed:{fetchData:function(){return{parent:this.options.parent}}},methods:{back:function(){this.options.parent=this.model.parent,this.pagination.page=1,this.fetch()},go:function(t){this.options.parent=t.id,this.pagination.page=1,this.fetch()},onFetched:function(t){this.model=t.model}}},Me=Re,ze=(n("ac27"),Object(_["a"])(Me,Pe,De,!1,null,null,null)),Ue=ze.exports,Fe={extends:ve,methods:{open:function(){var t=this;this.$api.site.get({select:["title"]}).then(function(e){t.page=e,t.$refs.dialog.open()}).catch(function(e){t.$store.dispatch("notification/error",e)})},submit:function(){var t=this;this.page.title=this.page.title.trim(),0!==this.page.title.length?this.$api.site.title(this.page.title).then(function(){t.$store.dispatch("system/title",t.page.title),t.success({message:":)",event:"site.changeTitle"})}).catch(function(e){t.$refs.dialog.error(e.message)}):this.$refs.dialog.error(this.$t("error.site.changeTitle.empty"))}}},He=Fe,Ke=Object(_["a"])(He,a,o,!1,null,null,null),Ve=Ke.exports,Ye=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("create"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()},close:t.reset}},[n("k-form",{ref:"form",attrs:{fields:t.fields,novalidate:!0},on:{submit:t.create},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}})],1)},We=[],Ge=n("795b"),Je=n.n(Ge),Ze=(n("5df3"),{mixins:[C],data:function(){return{user:this.emptyForm(),languages:[],roles:[]}},computed:{fields:function(){return{name:{label:this.$t("name"),type:"text",icon:"user"},email:{label:this.$t("email"),type:"email",icon:"email",link:!1,required:!0},password:{label:this.$t("password"),type:"password",icon:"key"},language:{label:this.$t("language"),type:"select",icon:"globe",options:this.languages,required:!0,empty:!1},role:{label:this.$t("role"),type:1===this.roles.length?"hidden":"radio",required:!0,options:this.roles}}}},methods:{create:function(){var t=this;this.$api.users.create(this.user).then(function(){t.success({message:":)",event:"user.create"})}).catch(function(e){t.$refs.dialog.error(e.message)})},emptyForm:function(){return{name:"",email:"",password:"",language:this.$store.state.system.info.defaultLanguage||"en",role:this.$user.role.name}},open:function(){var t=this,e=this.$api.roles.options({canBe:"created"}).then(function(e){t.roles=e,"admin"!==t.$user.role.name&&(t.roles=t.roles.filter(function(t){return"admin"!==t.value}))}).catch(function(e){t.$store.dispatch("notification/error",e)}),n=this.$api.translations.options().then(function(e){t.languages=e}).catch(function(e){t.$store.dispatch("notification/error",e)});Je.a.all([e,n]).then(function(){t.$refs.dialog.open()})},reset:function(){this.user=this.emptyForm()}}}),Xe=Ze,Qe=Object(_["a"])(Xe,Ye,We,!1,null,null,null),tn=Qe.exports,en=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}})],1)},nn=[],sn={mixins:[C],data:function(){return{user:{id:null,email:null}}},computed:{fields:function(){return{email:{label:this.$t("email"),preselect:!0,required:!0,type:"email"}}}},methods:{open:function(t){var e=this;this.$api.users.get(t,{select:["id","email"]}).then(function(t){e.user=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.users.changeEmail(this.user.id,this.user.email).then(function(e){t.$store.dispatch("content/revert","users/"+t.user.id),t.$user.id===t.user.id&&t.$store.dispatch("user/email",t.user.email);var n={message:":)",event:"user.changeEmail"};"User"===t.$route.name&&(n.route=t.$api.users.link(e.id)),t.success(n)}).catch(function(e){t.$refs.dialog.error(e.message)})}}},an=sn,on=Object(_["a"])(an,en,nn,!1,null,null,null),rn=on.exports,ln=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),theme:"positive",icon:"check"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}})],1)},un=[],cn={mixins:[C],data:function(){return{user:{language:"en"},languages:[]}},computed:{fields:function(){return{language:{label:this.$t("language"),type:"select",icon:"globe",options:this.languages,required:!0,empty:!1}}}},created:function(){var t=this;this.$api.translations.options().then(function(e){t.languages=e})},methods:{open:function(t){var e=this;this.$api.users.get(t,{view:"compact"}).then(function(t){e.user=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.users.changeLanguage(this.user.id,this.user.language).then(function(e){t.user=e,t.$user.id===t.user.id&&t.$store.dispatch("user/language",t.user.language),t.success({message:":)",event:"user.changeLanguage"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},dn=cn,pn=Object(_["a"])(dn,ln,un,!1,null,null,null),fn=pn.exports,hn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("change"),theme:"positive",icon:"check"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.values,callback:function(e){t.values=e},expression:"values"}})],1)},mn=[],gn={mixins:[C],data:function(){return{user:null,values:{password:null,passwordConfirmation:null}}},computed:{fields:function(){return{password:{label:this.$t("user.changePassword.new"),type:"password",icon:"key"},passwordConfirmation:{label:this.$t("user.changePassword.new.confirm"),icon:"key",type:"password"}}}},methods:{open:function(t){var e=this;this.$api.users.get(t).then(function(t){e.user=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;return!this.values.password||this.values.password.length<8?(this.$refs.dialog.error(this.$t("error.user.password.invalid")),!1):this.values.password!==this.values.passwordConfirmation?(this.$refs.dialog.error(this.$t("error.user.password.notSame")),!1):void this.$api.users.changePassword(this.user.id,this.values.password).then(function(){t.success({message:":)",event:"user.changePassword"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},bn=gn,vn=Object(_["a"])(bn,hn,mn,!1,null,null,null),kn=vn.exports,$n=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("delete"),theme:"negative",icon:"trash"},on:{submit:t.submit}},[n("k-text",{domProps:{innerHTML:t._s(t.$t("user.delete.confirm",{email:t.user.email}))}})],1)},_n=[],yn={mixins:[C],data:function(){return{user:{email:null}}},methods:{open:function(t){var e=this;this.$api.users.get(t).then(function(t){e.user=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.users.delete(this.user.id).then(function(){t.$store.dispatch("content/remove","users/"+t.user.id),t.success({message:":)",event:"user.delete"}),"User"===t.$route.name&&t.$router.push("/users")}).catch(function(e){t.$refs.dialog.error(e.message)})}}},xn=yn,wn=Object(_["a"])(xn,$n,_n,!1,null,null,null),On=wn.exports,Cn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("rename"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}})],1)},Sn=[],En={mixins:[C],data:function(){return{user:{id:null,name:null}}},computed:{fields:function(){return{name:{label:this.$t("name"),type:"text",icon:"user",preselect:!0}}}},methods:{open:function(t){var e=this;this.$api.users.get(t,{select:["id","name"]}).then(function(t){e.user=t,e.$refs.dialog.open()}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.user.name=this.user.name.trim(),this.$api.users.changeName(this.user.id,this.user.name).then(function(){t.$user.id===t.user.id&&t.$store.dispatch("user/name",t.user.name),t.success({message:":)",event:"user.changeName"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},jn=En,Tn=Object(_["a"])(jn,Cn,Sn,!1,null,null,null),In=Tn.exports,Ln=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("user.changeRole"),size:"medium",theme:"positive"},on:{submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}})],1)},qn=[],An={mixins:[C],data:function(){return{roles:[],user:{id:null,role:"visitor"}}},computed:{fields:function(){return{role:{label:this.$t("user.changeRole.select"),type:"radio",required:!0,options:this.roles}}}},methods:{open:function(t){var e=this;this.id=t,this.$api.users.get(t).then(function(t){e.$api.roles.options({canBe:"changed"}).then(function(n){e.roles=n,"admin"!==e.$user.role.name&&(e.roles=e.roles.filter(function(t){return"admin"!==t.value})),e.user=t,e.user.role=e.user.role.name,e.$refs.dialog.open()})}).catch(function(t){e.$store.dispatch("notification/error",t)})},submit:function(){var t=this;this.$api.users.changeRole(this.user.id,this.user.role).then(function(){t.$user.id===t.user.id&&t.$store.dispatch("user/load"),t.success({message:":)",event:"user.changeRole"})}).catch(function(e){t.$refs.dialog.error(e.message)})}}},Nn=An,Bn=Object(_["a"])(Nn,Ln,qn,!1,null,null,null),Pn=Bn.exports,Dn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",staticClass:"k-users-dialog",attrs:{size:"medium"},on:{cancel:function(e){return t.$emit("cancel")},submit:t.submit}},[t.issue?[n("k-box",{attrs:{text:t.issue,theme:"negative"}})]:[t.options.search?n("k-input",{staticClass:"k-dialog-search",attrs:{autofocus:!0,placeholder:t.$t("search")+" …",type:"text",icon:"search"},model:{value:t.search,callback:function(e){t.search=e},expression:"search"}}):t._e(),t.models.length?[n("k-list",t._l(t.models,function(e){return n("k-list-item",{key:e.email,attrs:{text:e.username,image:e.image,icon:e.icon},on:{click:function(n){return t.toggle(e)}}},[t.isSelected(e)?n("k-button",{attrs:{slot:"options",autofocus:!0,icon:t.checkedIcon,tooltip:t.$t("remove"),theme:"positive"},slot:"options"}):n("k-button",{attrs:{slot:"options",autofocus:!0,tooltip:t.$t("select"),icon:"circle-outline"},slot:"options"})],1)}),1),n("k-pagination",t._b({staticClass:"k-dialog-pagination",attrs:{details:!0,dropdown:!1,align:"center"},on:{paginate:t.paginate}},"k-pagination",t.pagination,!1))]:n("k-empty",{attrs:{icon:"users"}},[t._v("\n "+t._s(t.$t("dialog.users.empty"))+"\n ")])]],2)},Rn=[],Mn={mixins:[Ot]},zn=Mn,Un=(n("7568"),Object(_["a"])(zn,Dn,Rn,!1,null,null,null)),Fn=Un.exports,Hn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dropdown",{staticClass:"k-autocomplete"},[t._t("default"),n("k-dropdown-content",t._g({ref:"dropdown",attrs:{autofocus:!0}},t.$listeners),t._l(t.matches,function(e,i){return n("k-dropdown-item",t._b({key:i,on:{mousedown:function(n){return t.onSelect(e)},keydown:[function(n){return!n.type.indexOf("key")&&t._k(n.keyCode,"tab",9,n.key,"Tab")?null:(n.preventDefault(),t.onSelect(e))},function(n){return!n.type.indexOf("key")&&t._k(n.keyCode,"enter",13,n.key,"Enter")?null:(n.preventDefault(),t.onSelect(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"left",37,e.key,["Left","ArrowLeft"])?null:"button"in e&&0!==e.button?null:(e.preventDefault(),t.close(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"backspace",void 0,e.key,void 0)?null:(e.preventDefault(),t.close(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"delete",[8,46],e.key,["Backspace","Delete","Del"])?null:(e.preventDefault(),t.close(e))}]}},"k-dropdown-item",e,!1),[t._v("\n "+t._s(e.text)+"\n ")])}),1),t._v("\n "+t._s(t.query)+"\n")],2)},Kn=[],Vn=(n("4917"),n("3b2b"),{props:{limit:10,skip:{type:Array,default:function(){return[]}},options:Array,query:String},data:function(){return{matches:[],selected:{text:null}}},methods:{close:function(){this.$refs.dropdown.close()},onSelect:function(t){this.$refs.dropdown.close(),this.$emit("select",t)},search:function(t){var e=this;if(!(t.length<1)){var n=new RegExp(RegExp.escape(t),"ig");this.matches=this.options.filter(function(t){return!!t.text&&(-1===e.skip.indexOf(t.value)&&null!==t.text.match(n))}).slice(0,this.limit),this.$emit("search",t,this.matches),this.$refs.dropdown.open()}}}}),Yn=Vn,Wn=Object(_["a"])(Yn,Hn,Kn,!1,null,null,null),Gn=Wn.exports,Jn=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-calendar-input"},[n("nav",[n("k-button",{attrs:{icon:"angle-left"},on:{click:t.prev}}),n("span",{staticClass:"k-calendar-selects"},[n("k-select-input",{attrs:{options:t.months,disabled:t.disabled,required:!0},model:{value:t.month,callback:function(e){t.month=t._n(e)},expression:"month"}}),n("k-select-input",{attrs:{options:t.years,disabled:t.disabled,required:!0},model:{value:t.year,callback:function(e){t.year=t._n(e)},expression:"year"}})],1),n("k-button",{attrs:{icon:"angle-right"},on:{click:t.next}})],1),n("table",{staticClass:"k-calendar-table"},[n("thead",[n("tr",t._l(t.weekdays,function(e){return n("th",{key:"weekday_"+e},[t._v(t._s(e))])}),0)]),n("tbody",t._l(t.numberOfWeeks,function(e){return n("tr",{key:"week_"+e},t._l(t.days(e),function(e,i){return n("td",{key:"day_"+i,staticClass:"k-calendar-day",attrs:{"aria-current":!!t.isToday(e)&&"date","aria-selected":!!t.isCurrent(e)&&"date"}},[e?n("k-button",{on:{click:function(n){return t.select(e)}}},[t._v(t._s(e))]):t._e()],1)}),0)}),0),n("tfoot",[n("tr",[n("td",{staticClass:"k-calendar-today",attrs:{colspan:"7"}},[n("k-button",{on:{click:t.selectToday}},[t._v(t._s(t.$t("today")))])],1)])])])])},Zn=[],Xn={props:{value:String,disabled:Boolean},data:function(){var t=this.value?this.$library.dayjs(this.value):this.$library.dayjs();return{day:t.date(),month:t.month(),year:t.year(),today:this.$library.dayjs(),current:t}},computed:{date:function(){return this.$library.dayjs("".concat(this.year,"-").concat(this.month+1,"-").concat(this.day))},numberOfDays:function(){return this.date.daysInMonth()},numberOfWeeks:function(){return Math.ceil((this.numberOfDays+this.firstWeekday-1)/7)},firstWeekday:function(){var t=this.date.clone().startOf("month").day();return t>0?t:7},weekdays:function(){return[this.$t("days.mon"),this.$t("days.tue"),this.$t("days.wed"),this.$t("days.thu"),this.$t("days.fri"),this.$t("days.sat"),this.$t("days.sun")]},monthnames:function(){return[this.$t("months.january"),this.$t("months.february"),this.$t("months.march"),this.$t("months.april"),this.$t("months.may"),this.$t("months.june"),this.$t("months.july"),this.$t("months.august"),this.$t("months.september"),this.$t("months.october"),this.$t("months.november"),this.$t("months.december")]},months:function(){var t=[];return this.monthnames.forEach(function(e,n){t.push({value:n,text:e})}),t},years:function(){for(var t=[],e=this.year-10;e<=this.year+10;e++)t.push({value:e,text:this.$helper.pad(e)});return t}},watch:{value:function(t){var e=this.$library.dayjs(t);this.day=e.date(),this.month=e.month(),this.year=e.year(),this.current=e}},methods:{days:function(t){for(var e=[],n=7*(t-1)+1,i=n;ithis.numberOfDays?e.push(""):e.push(s)}return e},next:function(){var t=this.date.clone().add(1,"month");this.set(t)},isToday:function(t){return this.month===this.today.month()&&this.year===this.today.year()&&t===this.today.date()},isCurrent:function(t){return this.month===this.current.month()&&this.year===this.current.year()&&t===this.current.date()},prev:function(){var t=this.date.clone().subtract(1,"month");this.set(t)},go:function(t,e){"today"===t&&(t=this.today.year(),e=this.today.month()),this.year=t,this.month=e},set:function(t){this.day=t.date(),this.month=t.month(),this.year=t.year()},selectToday:function(){this.set(this.$library.dayjs()),this.select(this.day)},select:function(t){t&&(this.day=t);var e=this.$library.dayjs(new Date(this.year,this.month,this.day,this.current.hour(),this.current.minute()));this.$emit("input",e.toISOString())}}},Qn=Xn,ti=(n("ee15"),Object(_["a"])(Qn,Jn,Zn,!1,null,null,null)),ei=ti.exports,ni=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{staticClass:"k-counter",attrs:{"data-invalid":!t.valid}},[n("span",[t._v(t._s(t.count))]),t.min&&t.max?n("span",{staticClass:"k-counter-rules"},[t._v("("+t._s(t.min)+"–"+t._s(t.max)+")")]):t.min?n("span",{staticClass:"k-counter-rules"},[t._v("≥ "+t._s(t.min))]):t.max?n("span",{staticClass:"k-counter-rules"},[t._v("≤ "+t._s(t.max))]):t._e()])},ii=[],si=(n("c5f6"),{props:{count:Number,min:Number,max:Number,required:{type:Boolean,default:!1}},computed:{valid:function(){return!1===this.required&&0===this.count||(!0!==this.required||0!==this.count)&&(!(this.min&&this.countthis.max))}}}),ai=si,oi=(n("fc0f"),Object(_["a"])(ai,ni,ii,!1,null,null,null)),ri=oi.exports,li=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("form",{ref:"form",staticClass:"k-form",attrs:{method:"POST",autocomplete:"off",novalidate:""},on:{submit:function(e){return e.preventDefault(),t.onSubmit(e)}}},[t._t("header"),t._t("default",[n("k-fieldset",t._g({ref:"fields",attrs:{disabled:t.disabled,fields:t.fields,novalidate:t.novalidate},model:{value:t.value,callback:function(e){t.value=e},expression:"value"}},t.listeners))]),t._t("footer"),n("input",{ref:"submitter",staticClass:"k-form-submitter",attrs:{type:"submit"}})],2)},ui=[],ci={props:{disabled:Boolean,config:Object,fields:{type:[Array,Object],default:function(){return{}}},novalidate:{type:Boolean,default:!1},value:{type:Object,default:function(){return{}}}},data:function(){return{errors:{},listeners:Object(I["a"])({},this.$listeners,{submit:this.onSubmit})}},methods:{focus:function(t){this.$refs.fields&&this.$refs.fields.focus&&this.$refs.fields.focus(t)},onSubmit:function(){this.$emit("submit",this.value)},submit:function(){this.$refs.submitter.click()}}},di=ci,pi=(n("5d33"),Object(_["a"])(di,li,ui,!1,null,null,null)),fi=pi.exports,hi=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("nav",{staticClass:"k-form-buttons",attrs:{"data-theme":t.mode}},["unlock"===t.mode?n("k-view",[n("p",{staticClass:"k-form-lock-info"},[t._v("\n "+t._s(t.$t("lock.isUnlocked"))+"\n ")]),n("span",{staticClass:"k-form-lock-buttons"},[n("k-button",{staticClass:"k-form-button",attrs:{icon:"download"},on:{click:t.onDownload}},[t._v("\n "+t._s(t.$t("download"))+"\n ")]),n("k-button",{staticClass:"k-form-button",attrs:{icon:"check"},on:{click:t.onResolve}},[t._v("\n "+t._s(t.$t("confirm"))+"\n ")])],1)]):"lock"===t.mode?n("k-view",[n("p",{staticClass:"k-form-lock-info"},[n("k-icon",{attrs:{type:"lock"}}),n("span",{domProps:{innerHTML:t._s(t.$t("lock.isLocked",{email:t.form.lock.email}))}})],1),t.form.lock.unlockable?n("k-button",{staticClass:"k-form-button",attrs:{icon:"unlock"},on:{click:t.setUnlock}},[t._v("\n "+t._s(t.$t("lock.unlock"))+"\n ")]):n("k-icon",{staticClass:"k-form-lock-loader",attrs:{type:"loader"}})],1):"changes"===t.mode?n("k-view",[n("k-button",{staticClass:"k-form-button",attrs:{disabled:t.isDisabled,icon:"undo"},on:{click:t.onRevert}},[t._v("\n "+t._s(t.$t("revert"))+"\n ")]),n("k-button",{staticClass:"k-form-button",attrs:{disabled:t.isDisabled,icon:"check"},on:{click:t.onSave}},[t._v("\n "+t._s(t.$t("save"))+"\n ")])],1):t._e()],1)},mi=[],gi=n("75fc"),bi={data:function(){return{supportsLocking:!0}},computed:{api:function(){return{lock:[this.$route.path+"/lock",null,null,!0],unlock:[this.$route.path+"/unlock",null,null,!0]}},hasChanges:function(){return this.$store.getters["content/hasChanges"]()},form:function(){return{lock:this.$store.state.content.status.lock,unlock:this.$store.state.content.status.unlock}},id:function(){return this.$store.state.content.current},isDisabled:function(){return!1===this.$store.state.content.status.enabled},isLocked:function(){return null!==this.form.lock},isUnlocked:function(){return null!==this.form.unlock},mode:function(){return!0===this.isUnlocked?"unlock":!0===this.isLocked?"lock":!0===this.hasChanges?"changes":void 0}},watch:{hasChanges:function(t,e){if(!1===e&&!0===t)return this.$store.dispatch("heartbeat/remove",this.getLock),void this.$store.dispatch("heartbeat/add",[this.setLock,30]);this.id&&!0===e&&!1===t&&this.removeLock()},id:function(){this.id&&!1===this.hasChanges&&this.$store.dispatch("heartbeat/add",[this.getLock,10])}},created:function(){this.$events.$on("keydown.cmd.s",this.onSave)},destroyed:function(){this.$events.$off("keydown.cmd.s",this.onSave)},methods:{getLock:function(){var t,e=this;return(t=this.$api).get.apply(t,Object(gi["a"])(this.api.lock)).then(function(t){if(!1===t.supported)return e.supportsLocking=!1,void e.$store.dispatch("heartbeat/remove",e.getLock);!1===t.locked?(e.isLocked&&e.form.lock.user!==e.$store.state.user.current.id&&e.$events.$emit("model.reload"),e.$store.dispatch("content/lock",null)):e.$store.dispatch("content/lock",t.locked)}).catch(function(){})},setLock:function(){var t,e=this;!0===this.supportsLocking&&(t=this.$api).patch.apply(t,Object(gi["a"])(this.api.lock)).catch(function(t){if("error.lock.notImplemented"===t.key)return e.supportsLocking=!1,e.$store.dispatch("heartbeat/remove",e.setLock),!1;e.$store.dispatch("content/revert",e.id),e.$store.dispatch("heartbeat/remove",e.setLock),e.$store.dispatch("heartbeat/add",[e.getLock,10])})},removeLock:function(){var t,e=this;!0===this.supportsLocking&&(this.$store.dispatch("heartbeat/remove",this.setLock),(t=this.$api).delete.apply(t,Object(gi["a"])(this.api.lock)).then(function(){e.$store.dispatch("content/lock",null),e.$store.dispatch("heartbeat/add",[e.getLock,10])}).catch(function(){}))},setUnlock:function(){var t,e=this;!0===this.supportsLocking&&(this.$store.dispatch("heartbeat/remove",this.setLock),(t=this.$api).patch.apply(t,Object(gi["a"])(this.api.unlock)).then(function(){e.$store.dispatch("content/lock",null),e.$store.dispatch("heartbeat/add",[e.getLock,10])}).catch(function(){}))},removeUnlock:function(){var t,e=this;!0===this.supportsLocking&&(this.$store.dispatch("heartbeat/remove",this.setLock),(t=this.$api).delete.apply(t,Object(gi["a"])(this.api.unlock)).then(function(){e.$store.dispatch("content/unlock",null),e.$store.dispatch("heartbeat/add",[e.getLock,10])}).catch(function(){}))},onDownload:function(){var t=this,e="";kt()(this.form.unlock).forEach(function(n){e+=n+": \n\n"+t.form.unlock[n],e+="\n\n----\n\n"});var n=document.createElement("a");n.setAttribute("href","data:text/plain;charset=utf-8,"+encodeURIComponent(e)),n.setAttribute("download",this.id+".txt"),n.style.display="none",document.body.appendChild(n),n.click(),document.body.removeChild(n)},onResolve:function(){this.$store.dispatch("content/revert"),this.removeUnlock()},onRevert:function(){this.$store.dispatch("content/revert")},onSave:function(t){var e=this;return!!t&&(t.preventDefault&&t.preventDefault(),!1===this.hasChanges||void this.$store.dispatch("content/save").then(function(){e.$events.$emit("model.update"),e.$store.dispatch("notification/success",":)")}).catch(function(t){403!==t.code&&(t.details&&kt()(t.details).length>0?e.$store.dispatch("notification/error",{message:e.$t("error.form.incomplete"),details:t.details}):e.$store.dispatch("notification/error",{message:e.$t("error.form.notSaved"),details:[{label:"Exception: "+t.exception,message:t.message}]}))}))}}},vi=bi,ki=(n("18dd"),Object(_["a"])(vi,hi,mi,!1,null,null,null)),$i=ki.exports,_i=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.hasChanges?n("k-dropdown",{staticClass:"k-form-indicator"},[n("k-button",{staticClass:"k-topbar-button",on:{click:t.toggle}},[n("k-icon",{staticClass:"k-form-indicator-icon",attrs:{type:"edit"}})],1),n("k-dropdown-content",{ref:"list",attrs:{align:"right"}},[n("p",{staticClass:"k-form-indicator-info"},[t._v("\n "+t._s(t.$t("lock.unsaved"))+":\n ")]),n("hr"),t._l(t.entries,function(e){return n("k-dropdown-item",{key:e.id,attrs:{icon:e.icon},nativeOn:{click:function(n){return n.stopPropagation(),t.go(e.target)}}},[t._v("\n "+t._s(e.label)+"\n ")])})],2)],1):t._e()},yi=[],xi=(n("28a5"),n("f559"),{data:function(){return{isOpen:!1,entries:[]}},computed:{store:function(){return this.$store.state.content.models},models:function(){var t=this,e=kt()(this.store).filter(function(e){return!!t.store[e]}),n=e.map(function(e){return Object(I["a"])({id:e},t.store[e])});return n.filter(function(t){return kt()(t.changes).length>0})},hasChanges:function(){return this.models.length>0}},methods:{go:function(t){if(t.language&&this.$store.state.languages.current.code!==t.language){var e=this.$store.state.languages.all.filter(function(e){return e.code===t.language})[0];this.$store.dispatch("languages/current",e)}this.$router.push(t.link)},load:function(){var t=this,e=this.models.map(function(e){return t.$api.get(e.api,{view:"compact"},null,!0).then(function(n){var i;if(i=!0===e.id.startsWith("pages/")?{icon:"page",label:n.title,target:{link:t.$api.pages.link(n.id)}}:!0===e.id.startsWith("files/")?{icon:"image",label:n.filename,target:{link:n.link}}:!0===e.id.startsWith("users/")?{icon:"user",label:n.email,target:{link:t.$api.users.link(n.id)}}:{icon:"home",label:n.title,target:{link:"/site"}},t.$store.state.languages.current){var s=e.id.split("/").pop();i.label=i.label+" ("+s+")",i.target.language=s}return i}).catch(function(){return t.$store.dispatch("content/remove",e.id),null})});return Je.a.all(e).then(function(e){t.entries=e.filter(function(t){return null!==t}),0===t.entries.length&&t.$store.dispatch("notification/success",t.$t("lock.unsaved.empty"))})},toggle:function(){var t=this;!1===this.$refs.list.isOpen?this.load().then(function(){t.$refs.list&&t.$refs.list.toggle()}):this.$refs.list.toggle()}}}),wi=xi,Oi=(n("9e26"),Object(_["a"])(wi,_i,yi,!1,null,null,null)),Ci=Oi.exports,Si=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{class:"k-field k-field-name-"+t.name,attrs:{"data-disabled":t.disabled},on:{focusin:function(e){return t.$emit("focus",e)},focusout:function(e){return t.$emit("blur",e)}}},[t._t("header",[n("header",{staticClass:"k-field-header"},[t._t("label",[n("label",{staticClass:"k-field-label",attrs:{for:t.input}},[t._v(t._s(t.labelText)+" "),t.required?n("abbr",{attrs:{title:t.$t("field.required")}},[t._v("*")]):t._e()])]),t._t("options"),t._t("counter",[t.counter?n("k-counter",t._b({staticClass:"k-field-counter",attrs:{required:t.required}},"k-counter",t.counter,!1)):t._e()])],2)]),t._t("default"),t._t("footer",[t.help||t.$slots.help?n("footer",{staticClass:"k-field-footer"},[t._t("help",[t.help?n("k-text",{staticClass:"k-field-help",attrs:{theme:"help"},domProps:{innerHTML:t._s(t.help)}}):t._e()])],2):t._e()])],2)},Ei=[],ji={inheritAttrs:!1,props:{counter:[Boolean,Object],disabled:Boolean,endpoints:Object,help:String,input:[String,Number],label:String,name:[String,Number],required:Boolean,type:String},computed:{labelText:function(){return this.label||" "}}},Ti=ji,Ii=(n("a134"),Object(_["a"])(Ti,Si,Ei,!1,null,null,null)),Li=Ii.exports,qi=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("fieldset",{staticClass:"k-fieldset"},[n("k-grid",t._l(t.fields,function(e,i){return"hidden"!==e.type&&t.meetsCondition(e)?n("k-column",{key:e.signature,attrs:{width:e.width}},[n("k-error-boundary",[t.hasFieldType(e.type)?n("k-"+e.type+"-field",t._b({ref:i,refInFor:!0,tag:"component",attrs:{name:i,novalidate:t.novalidate,disabled:t.disabled||e.disabled},on:{input:function(n){return t.$emit("input",t.value,e,i)},focus:function(n){return t.$emit("focus",n,e,i)},invalid:function(n,s){return t.onInvalid(n,s,e,i)},submit:function(n){return t.$emit("submit",n,e,i)}},model:{value:t.value[i],callback:function(e){t.$set(t.value,i,e)},expression:"value[fieldName]"}},"component",e,!1)):n("k-box",{attrs:{theme:"negative"}},[n("k-text",{attrs:{size:"small"}},[t._v("\n The field type "),n("strong",[t._v('"'+t._s(i)+'"')]),t._v(" does not exist\n ")])],1)],1)],1):t._e()}),1)],1)},Ai=[],Ni={props:{config:Object,disabled:Boolean,fields:{type:[Array,Object],default:function(){return[]}},novalidate:{type:Boolean,default:!1},value:{type:Object,default:function(){return{}}}},data:function(){return{errors:{}}},methods:{focus:function(t){if(t)this.hasField(t)&&"function"===typeof this.$refs[t][0].focus&&this.$refs[t][0].focus();else{var e=kt()(this.$refs)[0];this.focus(e)}},hasFieldType:function(t){return z["a"].options.components["k-"+t+"-field"]},hasField:function(t){return this.$refs[t]&&this.$refs[t][0]},meetsCondition:function(t){var e=this;if(!t.when)return!0;var n=!0;return kt()(t.when).forEach(function(i){var s=e.value[i.toLowerCase()],a=t.when[i];s!==a&&(n=!1)}),n},onInvalid:function(t,e,n,i){this.errors[i]=e,this.$emit("invalid",this.errors)},hasErrors:function(){return kt()(this.errors).length}}},Bi=Ni,Pi=(n("862b"),Object(_["a"])(Bi,qi,Ai,!1,null,null,null)),Di=Pi.exports,Ri=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-input",attrs:{"data-disabled":t.disabled,"data-invalid":!t.novalidate&&t.isInvalid,"data-theme":t.theme,"data-type":t.type}},[t.$slots.before||t.before?n("span",{staticClass:"k-input-before",on:{click:t.focus}},[t._t("before",[t._v(t._s(t.before))])],2):t._e(),n("span",{staticClass:"k-input-element",on:{click:function(e){return e.stopPropagation(),t.focus(e)}}},[t._t("default",[n("k-"+t.type+"-input",t._g(t._b({ref:"input",tag:"component",attrs:{value:t.value}},"component",t.inputProps,!1),t.listeners))])],2),t.$slots.after||t.after?n("span",{staticClass:"k-input-after",on:{click:t.focus}},[t._t("after",[t._v(t._s(t.after))])],2):t._e(),t.$slots.icon||t.icon?n("span",{staticClass:"k-input-icon",on:{click:t.focus}},[t._t("icon",[n("k-icon",{attrs:{type:t.icon}})])],2):t._e()])},Mi=[],zi={inheritAttrs:!1,props:{after:String,before:String,disabled:Boolean,type:String,icon:[String,Boolean],invalid:Boolean,theme:String,novalidate:{type:Boolean,default:!1},value:{type:[String,Boolean,Number,Object,Array],default:null}},data:function(){var t=this;return{isInvalid:this.invalid,listeners:Object(I["a"])({},this.$listeners,{invalid:function(e,n){t.isInvalid=e,t.$emit("invalid",e,n)}})}},computed:{inputProps:function(){return Object(I["a"])({},this.$props,this.$attrs)}},methods:{blur:function(t){t.relatedTarget&&!1===this.$el.contains(t.relatedTarget)&&this.$refs.input.blur&&this.$refs.input.blur()},focus:function(t){if(t&&t.target&&"INPUT"===t.target.tagName)t.target.focus();else if(this.$refs.input&&this.$refs.input.focus)this.$refs.input.focus();else{var e=this.$el.querySelector("input, select, textarea");e&&e.focus()}}}},Ui=zi,Fi=(n("c7c8"),Object(_["a"])(Ui,Ri,Mi,!1,null,null,null)),Hi=Fi.exports,Ki=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-upload"},[n("input",{ref:"input",attrs:{accept:t.options.accept,multiple:t.options.multiple,"aria-hidden":"true",type:"file",tabindex:"-1"},on:{change:t.select,click:function(t){t.stopPropagation()}}}),n("k-dialog",{ref:"dialog",attrs:{size:"medium"}},[t.errors.length>0?[n("k-headline",[t._v(t._s(t.$t("upload.errors")))]),n("ul",{staticClass:"k-upload-error-list"},t._l(t.errors,function(e,i){return n("li",{key:"error-"+i},[n("p",{staticClass:"k-upload-error-filename"},[t._v(t._s(e.file.name))]),n("p",{staticClass:"k-upload-error-message"},[t._v(t._s(e.message))])])}),0)]:[n("k-headline",[t._v(t._s(t.$t("upload.progress")))]),n("ul",{staticClass:"k-upload-list"},t._l(t.files,function(e,i){return n("li",{key:"file-"+i},[n("k-progress",{ref:e.name,refInFor:!0}),n("p",{staticClass:"k-upload-list-filename"},[t._v(t._s(e.name))]),n("p",[t._v(t._s(t.errors[e.name]))])],1)}),0)],n("template",{slot:"footer"},[t.errors.length>0?[n("k-button-group",[n("k-button",{attrs:{icon:"check"},on:{click:function(e){return t.$refs.dialog.close()}}},[t._v("\n "+t._s(t.$t("confirm"))+"\n ")])],1)]:t._e()],2)],2)],1)},Vi=[],Yi=n("5176"),Wi=n.n(Yi),Gi={props:{url:{type:String},accept:{type:String,default:"*"},attributes:{type:Object},multiple:{type:Boolean,default:!0},max:{type:Number}},data:function(){return{options:this.$props,completed:{},errors:[],files:[],total:0}},methods:{open:function(t){var e=this;this.params(t),setTimeout(function(){e.$refs.input.click()},1)},params:function(t){this.options=Wi()({},this.$props,t)},select:function(t){this.upload(t.target.files)},drop:function(t,e){this.params(e),this.upload(t)},upload:function(t){var e=this;this.$refs.dialog.open(),this.files=Object(gi["a"])(t),this.completed={},this.errors=[],this.hasErrors=!1,this.options.max&&(this.files=this.files.slice(0,this.options.max)),this.total=this.files.length,this.files.forEach(function(t){e.$helper.upload(t,{url:e.options.url,attributes:e.options.attributes,headers:{"X-CSRF":window.panel.csrf},progress:function(t,n,i){e.$refs[n.name]&&e.$refs[n.name][0]&&e.$refs[n.name][0].set(i)},success:function(t,n,i){e.complete(n,i.data)},error:function(t,n,i){e.errors.push({file:n,message:i.message}),e.complete(n,i.data)}})})},complete:function(t,e){var n=this;if(this.completed[t.name]=e,kt()(this.completed).length==this.total){if(this.$refs.input.value="",this.errors.length>0)return this.$forceUpdate(),void this.$emit("error",this.files);setTimeout(function(){n.$refs.dialog.close(),n.$emit("success",n.files,_t()(n.completed))},250)}}}},Ji=Gi,Zi=(n("5aee"),Object(_["a"])(Ji,Ki,Vi,!1,null,null,null)),Xi=Zi.exports,Qi=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("label",{staticClass:"k-checkbox-input",on:{click:function(t){t.stopPropagation()}}},[n("input",{ref:"input",staticClass:"k-checkbox-input-native",attrs:{disabled:t.disabled,id:t.id,type:"checkbox"},domProps:{checked:t.value},on:{change:function(e){return t.onChange(e.target.checked)}}}),n("span",{staticClass:"k-checkbox-input-icon",attrs:{"aria-hidden":"true"}},[n("svg",{attrs:{width:"12",height:"10",viewBox:"0 0 12 10",xmlns:"http://www.w3.org/2000/svg"}},[n("path",{attrs:{d:"M1 5l3.3 3L11 1","stroke-width":"2",fill:"none","fill-rule":"evenodd"}})])]),n("span",{staticClass:"k-checkbox-input-label",domProps:{innerHTML:t._s(t.label)}})])},ts=[],es=n("b5ae"),ns={inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[Number,String],label:String,required:Boolean,value:Boolean},watch:{value:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$refs.input.focus()},onChange:function(t){this.$emit("input",t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},select:function(){this.focus()}},validations:function(){return{value:{required:!this.required||es["required"]}}}},is=ns,ss=(n("42e4"),Object(_["a"])(is,Qi,ts,!1,null,null,null)),as=ss.exports,os=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"k-checkboxes-input",style:"--columns:"+t.columns},t._l(t.options,function(e,i){return n("li",{key:i},[n("k-checkbox-input",{attrs:{id:t.id+"-"+i,label:e.text,value:-1!==t.selected.indexOf(e.value)},on:{input:function(n){return t.onInput(e.value,n)}}})],1)}),0)},rs=[],ls={inheritAttrs:!1,props:{autofocus:Boolean,columns:Number,disabled:Boolean,id:{type:[Number,String],default:function(){return this._uid}},max:Number,min:Number,options:Array,required:Boolean,value:{type:[Array,Object],default:function(){return[]}}},data:function(){return{selected:this.valueToArray(this.value)}},watch:{value:function(t){this.selected=this.valueToArray(t)},selected:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$el.querySelector("input").focus()},onInput:function(t,e){if(!0===e)this.selected.push(t);else{var n=this.selected.indexOf(t);-1!==n&&this.selected.splice(n,1)}this.$emit("input",this.selected)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},select:function(){this.focus()},valueToArray:function(t){return!0===xt()(t)?t:"string"===typeof t?String(t).split(","):"object"===Object(Ht["a"])(t)?_t()(t):void 0}},validations:function(){return{selected:{required:!this.required||es["required"],min:!this.min||Object(es["minLength"])(this.min),max:!this.max||Object(es["maxLength"])(this.max)}}}},us=ls,cs=Object(_["a"])(us,os,rs,!1,null,null,null),ds=cs.exports,ps=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-date-input"},[n("k-select-input",{ref:"years",attrs:{"aria-label":t.$t("year"),options:t.years,disabled:t.disabled,required:t.required,value:t.year,placeholder:"––––"},on:{input:t.setYear,invalid:t.onInvalid}}),n("span",{staticClass:"k-date-input-separator"},[t._v("-")]),n("k-select-input",{ref:"months",attrs:{"aria-label":t.$t("month"),options:t.months,disabled:t.disabled,required:t.required,value:t.month,placeholder:"––"},on:{input:t.setMonth,invalid:t.onInvalid}}),n("span",{staticClass:"k-date-input-separator"},[t._v("-")]),n("k-select-input",{ref:"days",attrs:{"aria-label":t.$t("day"),autofocus:t.autofocus,id:t.id,options:t.days,disabled:t.disabled,required:t.required,value:t.day,placeholder:"––"},on:{input:t.setDay,invalid:t.onInvalid}})],1)},fs=[],hs=n("e814"),ms=n.n(hs),gs={inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[String,Number],max:String,min:String,required:Boolean,value:String},data:function(){return{date:this.$library.dayjs(this.value),minDate:this.calculate(this.min,"min"),maxDate:this.calculate(this.max,"max")}},computed:{day:function(){return isNaN(this.date.date())?"":this.date.date()},days:function(){return this.options(1,this.date.daysInMonth()||31,"days")},month:function(){return isNaN(this.date.date())?"":this.date.month()+1},months:function(){return this.options(1,12,"months")},year:function(){return isNaN(this.date.year())?"":this.date.year()},years:function(){var t=this.date.isBefore(this.minDate)?this.date.year():this.minDate.year(),e=this.date.isAfter(this.maxDate)?this.date.year():this.maxDate.year();return this.options(t,e)}},watch:{value:function(t){this.date=this.$library.dayjs(t)}},methods:{calculate:function(t,e){var n={min:{run:"subtract",take:"startOf"},max:{run:"add",take:"endOf"}}[e],i=t?this.$library.dayjs(t):null;return i&&!1!==i.isValid()||(i=this.$library.dayjs()[n.run](10,"year")[n.take]("year")),i},focus:function(){this.$refs.years.focus()},onInput:function(){!1!==this.date.isValid()?this.$emit("input",this.date.toISOString()):this.$emit("input","")},onInvalid:function(t,e){this.$emit("invalid",t,e)},options:function(t,e){for(var n=[],i=t;i<=e;i++)n.push({value:i,text:this.$helper.pad(i)});return n},set:function(t,e){if(""===e||null===e||!1===e||-1===e)return this.setInvalid(),void this.onInput();if(!1===this.date.isValid())return this.setInitialDate(t,e),void this.onInput();var n=this.date,i=this.date.date();this.date=this.date.set(t,ms()(e)),"month"===t&&this.date.date()!==i&&(this.date=n.set("date",1).set("month",e).endOf("month")),this.onInput()},setInvalid:function(){this.date=this.$library.dayjs("invalid")},setInitialDate:function(t,e){var n=this.$library.dayjs();return this.date=this.$library.dayjs().set(t,ms()(e)),"date"===t&&n.month()!==this.date.month()&&(this.date=n.endOf("month")),this.date},setDay:function(t){this.set("date",t)},setMonth:function(t){this.set("month",t-1)},setYear:function(t){this.set("year",t)}}},bs=gs,vs=(n("6ab3"),Object(_["a"])(bs,ps,fs,!1,null,null,null)),ks=vs.exports,$s=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-datetime-input"},[n("k-date-input",{ref:"dateInput",attrs:{autofocus:t.autofocus,required:t.required,id:t.id,min:t.min,max:t.max,disabled:t.disabled,value:t.dateValue},on:{input:t.setDate}}),n("k-time-input",t._b({ref:"timeInput",attrs:{required:t.required,disabled:t.disabled,value:t.timeValue},on:{input:t.setTime}},"k-time-input",t.timeOptions,!1))],1)},_s=[],ys={inheritAttrs:!1,props:Object(I["a"])({},ks.props,{time:{type:[Boolean,Object],default:function(){return{}}},value:String}),data:function(){return{dateValue:this.parseDate(this.value),timeValue:this.parseTime(this.value),timeOptions:this.setTimeOptions()}},watch:{value:function(t){this.dateValue=this.parseDate(t),this.timeValue=this.parseTime(t),this.onInvalid()}},mounted:function(){this.onInvalid()},methods:{focus:function(){this.$refs.dateInput.focus()},onInput:function(){if(this.timeValue&&this.dateValue){var t=this.dateValue+"T"+this.timeValue+":00";this.$emit("input",t)}else this.$emit("input","")},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},parseDate:function(t){var e=this.$library.dayjs(t);return e.isValid()?e.format("YYYY-MM-DD"):null},parseTime:function(t){var e=this.$library.dayjs(t);return e.isValid()?e.format("HH:mm"):null},setDate:function(t){t&&!this.timeValue&&(this.timeValue=this.$library.dayjs().format("HH:mm")),t?this.dateValue=this.parseDate(t):(this.dateValue=null,this.timeValue=null),this.onInput()},setTime:function(t){t&&!this.dateValue&&(this.dateValue=this.$library.dayjs().format("YYYY-MM-DD")),t?this.timeValue=t:(this.dateValue=null,this.timeValue=null),this.onInput()},setTimeOptions:function(){return!0===this.time?{}:this.time}},validations:function(){return{value:{required:!this.required||es["required"]}}}},xs=ys,ws=(n("4433"),Object(_["a"])(xs,$s,_s,!1,null,null,null)),Os=ws.exports,Cs=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("input",t._g(t._b({ref:"input",staticClass:"k-text-input"},"input",{autocomplete:t.autocomplete,autofocus:t.autofocus,disabled:t.disabled,id:t.id,minlength:t.minlength,name:t.name,pattern:t.pattern,placeholder:t.placeholder,required:t.required,spellcheck:t.spellcheck,type:t.type,value:t.value},!1),t.listeners))},Ss=[],Es={inheritAttrs:!1,class:"k-text-input",props:{autocomplete:{type:[Boolean,String],default:"off"},autofocus:Boolean,disabled:Boolean,id:[Number,String],maxlength:Number,minlength:Number,name:[Number,String],pattern:String,placeholder:String,preselect:Boolean,required:Boolean,spellcheck:{type:[Boolean,String],default:"off"},type:{type:String,default:"text"},value:String},data:function(){var t=this;return{listeners:Object(I["a"])({},this.$listeners,{input:function(e){return t.onInput(e.target.value)}})}},watch:{value:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus(),this.$props.preselect&&this.select()},methods:{focus:function(){this.$refs.input.focus()},onInput:function(t){this.$emit("input",t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},select:function(){this.$refs.input.select()}},validations:function(){var t=this,e=function(e){return!t.required&&0===e.length||!t.$refs.input.validity.patternMismatch};return{value:{required:!this.required||es["required"],minLength:!this.minlength||Object(es["minLength"])(this.minlength),maxLength:!this.maxlength||Object(es["maxLength"])(this.maxlength),email:"email"!==this.type||es["email"],url:"url"!==this.type||es["url"],pattern:!this.pattern||e}}}},js=Es,Ts=(n("cb8f"),Object(_["a"])(js,Cs,Ss,!1,null,null,null)),Is=Ts.exports,Ls={extends:Is,props:Object(I["a"])({},Is.props,{autocomplete:{type:String,default:"email"},placeholder:{type:String,default:function(){return this.$t("email.placeholder")}},type:{type:String,default:"email"}})},qs=Ls,As=Object(_["a"])(qs,r,l,!1,null,null,null),Ns=As.exports,Bs=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-draggable",{staticClass:"k-multiselect-input",attrs:{list:t.state,options:t.dragOptions,"data-layout":t.layout,element:"k-dropdown"},on:{end:t.onInput},nativeOn:{click:function(e){return t.$refs.dropdown.toggle(e)}}},[t._l(t.sorted,function(e){return n("k-tag",{key:e.value,ref:e.value,refInFor:!0,attrs:{removable:!0},on:{remove:function(n){return t.remove(e)}},nativeOn:{click:function(t){t.stopPropagation()},keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"left",37,e.key,["Left","ArrowLeft"])?null:"button"in e&&0!==e.button?null:t.navigate("prev")},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"right",39,e.key,["Right","ArrowRight"])?null:"button"in e&&2!==e.button?null:t.navigate("next")},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"down",40,e.key,["Down","ArrowDown"])?null:t.$refs.dropdown.open(e)}]}},[t._v("\n "+t._s(e.text)+"\n ")])}),n("k-dropdown-content",{ref:"dropdown",attrs:{slot:"footer"},on:{open:t.onOpen,close:t.onClose},nativeOn:{keydown:function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"esc",27,e.key,["Esc","Escape"])?null:(e.stopPropagation(),t.close(e))}},slot:"footer"},[t.search?n("k-dropdown-item",{staticClass:"k-multiselect-search",attrs:{icon:"search"}},[n("input",{directives:[{name:"model",rawName:"v-model",value:t.q,expression:"q"}],ref:"search",domProps:{value:t.q},on:{keydown:function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"esc",27,e.key,["Esc","Escape"])?null:(e.stopPropagation(),t.escape(e))},input:function(e){e.target.composing||(t.q=e.target.value)}}})]):t._e(),n("div",{staticClass:"k-multiselect-options"},t._l(t.filtered,function(e){return n("k-dropdown-item",{key:e.value,class:{"k-multiselect-option":!0,selected:t.isSelected(e),disabled:!t.addable},attrs:{icon:t.isSelected(e)?"check":"circle-outline"},on:{click:function(n){return n.preventDefault(),t.select(e)}},nativeOn:{keydown:[function(n){return!n.type.indexOf("key")&&t._k(n.keyCode,"enter",13,n.key,"Enter")?null:(n.preventDefault(),n.stopPropagation(),t.select(e))},function(n){return!n.type.indexOf("key")&&t._k(n.keyCode,"space",32,n.key,[" ","Spacebar"])?null:(n.preventDefault(),n.stopPropagation(),t.select(e))}]}},[n("span",{domProps:{innerHTML:t._s(e.display)}}),n("span",{staticClass:"k-multiselect-value",domProps:{innerHTML:t._s(e.info)}})])}),1)],1)],2)},Ps=[],Ds=(n("20d6"),n("55dd"),{inheritAttrs:!1,props:{disabled:Boolean,id:[Number,String],max:Number,min:Number,layout:String,options:{type:Array,default:function(){return[]}},required:Boolean,search:Boolean,separator:{type:String,default:","},sort:Boolean,value:{type:Array,required:!0,default:function(){return[]}}},data:function(){return{state:this.value,q:null,scrollTop:0}},computed:{addable:function(){return!this.max||this.state.length1&&!this.sort},dragOptions:function(){return{disabled:!this.draggable,draggable:".k-tag",delay:1}},filtered:function(){if(null===this.q)return this.options.map(function(t){return Object(I["a"])({},t,{display:t.text,info:t.value})});var t=new RegExp("(".concat(RegExp.escape(this.q),")"),"ig");return this.options.filter(function(e){return e.text.match(t)||e.value.match(t)}).map(function(e){return Object(I["a"])({},e,{display:e.text.replace(t,"$1"),info:e.value.replace(t,"$1")})})},sorted:function(){var t=this;if(!1===this.sort)return this.state;var e=this.state,n=function(e){return t.options.findIndex(function(t){return t.value===e.value})};return e.sort(function(t,e){return n(t)-n(e)})}},watch:{value:function(t){this.state=t,this.onInvalid()}},mounted:function(){this.onInvalid(),this.$events.$on("click",this.close),this.$events.$on("keydown.cmd.s",this.close)},destroyed:function(){this.$events.$off("click",this.close),this.$events.$off("keydown.cmd.s",this.close)},methods:{add:function(t){!0===this.addable&&(this.state.push(t),this.onInput())},blur:function(){this.close()},close:function(){this.$refs.dropdown.close(),this.onClose()},escape:function(){this.q?this.q=null:this.close()},focus:function(){this.$refs.dropdown.open()},index:function(t){return this.state.findIndex(function(e){return e.value===t.value})},isSelected:function(t){return-1!==this.index(t)},navigate:function(t){var e=document.activeElement;switch(t){case"prev":e&&e.previousSibling&&e.previousSibling.focus&&e.previousSibling.focus();break;case"next":e&&e.nextSibling&&e.nextSibling.focus&&e.nextSibling.focus();break}},onClose:function(){this.q=null,this.$parent.$el.focus()},onInput:function(){this.$emit("input",this.sorted)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},onOpen:function(){var t=this;this.$nextTick(function(){t.$refs.search&&t.$refs.search.focus&&t.$refs.search.focus(),t.$refs.dropdown.$el.querySelector(".k-multiselect-options").scrollTop=t.scrollTop})},remove:function(t){this.state.splice(this.index(t),1),this.onInput()},select:function(t){this.scrollTop=this.$refs.dropdown.$el.querySelector(".k-multiselect-options").scrollTop,t={text:t.text,value:t.value},this.isSelected(t)?this.remove(t):this.add(t)}},validations:function(){return{state:{required:!this.required||es["required"],minLength:!this.min||Object(es["minLength"])(this.min),maxLength:!this.max||Object(es["maxLength"])(this.max)}}}}),Rs=Ds,Ms=(n("11ae"),Object(_["a"])(Rs,Bs,Ps,!1,null,null,null)),zs=Ms.exports,Us=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("input",t._g(t._b({ref:"input",staticClass:"k-number-input",attrs:{type:"number"},domProps:{value:t.number}},"input",{autofocus:t.autofocus,disabled:t.disabled,id:t.id,max:t.max,min:t.min,name:t.name,placeholder:t.placeholder,required:t.required,step:t.step},!1),t.listeners))},Fs=[],Hs=n("59ad"),Ks=n.n(Hs),Vs=(n("6b54"),{inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[Number,String],max:Number,min:Number,name:[Number,String],placeholder:String,preselect:Boolean,required:Boolean,step:Number,value:{type:[Number,String],default:null}},data:function(){var t=this;return{number:this.format(this.value),listeners:Object(I["a"])({},this.$listeners,{change:function(e){return t.onChange(e.target.value)},input:function(e){return t.onInput(e.target.value)}})}},watch:{value:function(t){this.number=t},number:{immediate:!0,handler:function(){this.onInvalid()}}},mounted:function(){this.$props.autofocus&&this.focus(),this.$props.preselect&&this.select()},methods:{decimals:function(){return Math.floor(this.step)===this.step?0:this.step.toString().split(".")[1].length||0},format:function(t){var e=this.decimals();return e?Ks()(t).toFixed(e):ms()(t)},focus:function(){this.$refs.input.focus()},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},onInput:function(t){this.number=t,this.$emit("input",this.number)},onChange:function(t){this.number=this.format(t),this.$emit("input",this.number)},select:function(){this.$refs.input.select()}},validations:function(){return{value:{required:!this.required||es["required"],min:!this.min||Object(es["minValue"])(this.min),max:!this.max||Object(es["maxValue"])(this.max)}}}}),Ys=Vs,Ws=(n("6018"),Object(_["a"])(Ys,Us,Fs,!1,null,null,null)),Gs=Ws.exports,Js={extends:Is,props:Object(I["a"])({},Is.props,{autocomplete:{type:String,default:"new-password"},type:{type:String,default:"password"}})},Zs=Js,Xs=Object(_["a"])(Zs,u,c,!1,null,null,null),Qs=Xs.exports,ta=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"k-radio-input",style:"--columns:"+t.columns},t._l(t.options,function(e,i){return n("li",{key:i},[n("input",{staticClass:"k-radio-input-native",attrs:{id:t.id+"-"+i,name:t.id,type:"radio"},domProps:{value:e.value,checked:t.value===e.value},on:{change:function(n){return t.onInput(e.value)}}}),n("label",{attrs:{for:t.id+"-"+i}},[e.info?[n("span",{staticClass:"k-radio-input-text"},[t._v(t._s(e.text))]),n("span",{staticClass:"k-radio-input-info"},[t._v(t._s(e.info))])]:[t._v("\n "+t._s(e.text)+"\n ")]],2),e.icon?n("k-icon",{attrs:{type:e.icon}}):t._e()],1)}),0)},ea=[],na={inheritAttrs:!1,props:{autofocus:Boolean,columns:Number,disabled:Boolean,id:{type:[Number,String],default:function(){return this._uid}},options:Array,required:Boolean,value:[String,Number,Boolean]},watch:{value:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$el.querySelector("input").focus()},onInput:function(t){this.$emit("input",t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},select:function(){this.focus()}},validations:function(){return{value:{required:!this.required||es["required"]}}}},ia=na,sa=(n("893d"),Object(_["a"])(ia,ta,ea,!1,null,null,null)),aa=sa.exports,oa=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("label",{staticClass:"k-range-input"},[n("input",t._g(t._b({ref:"input",staticClass:"k-range-input-native",style:"--min: "+t.min+"; --max: "+t.max+"; --value: "+t.position,attrs:{type:"range"},domProps:{value:t.position}},"input",{autofocus:t.autofocus,disabled:t.disabled,id:t.id,max:t.max,min:t.min,name:t.name,required:t.required,step:t.step},!1),t.listeners)),t.tooltip?n("span",{staticClass:"k-range-input-tooltip"},[t.tooltip.before?n("span",{staticClass:"k-range-input-tooltip-before"},[t._v(t._s(t.tooltip.before))]):t._e(),n("span",{staticClass:"k-range-input-tooltip-text"},[t._v(t._s(t.label))]),t.tooltip.after?n("span",{staticClass:"k-range-input-tooltip-after"},[t._v(t._s(t.tooltip.after))]):t._e()]):t._e()])},ra=[],la={inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[String,Number],default:[Number,String],max:{type:Number,default:100},min:{type:Number,default:0},name:[String,Number],required:Boolean,step:{type:Number,default:1},tooltip:{type:[Boolean,Object],default:function(){return{before:null,after:null}}},value:[Number,String]},data:function(){var t=this;return{listeners:Object(I["a"])({},this.$listeners,{input:function(e){return t.onInput(e.target.value)}})}},computed:{baseline:function(){return this.min<0?0:this.min},label:function(){return this.required||this.value?this.format(this.position):"–"},position:function(){return this.value||this.default||this.baseline}},watch:{position:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$refs.input.focus()},format:function(t){var e=document.lang?document.lang.replace("_","-"):"en",n=this.step.toString().split("."),i=n.length>1?n[1].length:0;return new Intl.NumberFormat(e,{minimumFractionDigits:i}).format(t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},onInput:function(t){this.$emit("input",t)}},validations:function(){return{position:{required:!this.required||es["required"],min:!this.min||Object(es["minValue"])(this.min),max:!this.max||Object(es["maxValue"])(this.max)}}}},ua=la,ca=(n("b5d2"),Object(_["a"])(ua,oa,ra,!1,null,null,null)),da=ca.exports,pa=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{staticClass:"k-select-input",attrs:{"data-disabled":t.disabled,"data-empty":""===t.selected}},[n("select",t._g({ref:"input",staticClass:"k-select-input-native",attrs:{autofocus:t.autofocus,"aria-label":t.ariaLabel,disabled:t.disabled,id:t.id,name:t.name,required:t.required},domProps:{value:t.selected}},t.listeners),[t.hasEmptyOption?n("option",{attrs:{disabled:t.required,value:""}},[t._v("\n "+t._s(t.emptyOption)+"\n ")]):t._e(),t._l(t.options,function(e){return n("option",{key:e.value,attrs:{disabled:e.disabled},domProps:{value:e.value}},[t._v("\n "+t._s(e.text)+"\n ")])})],2),t._v("\n "+t._s(t.label)+"\n")])},fa=[],ha={inheritAttrs:!1,props:{autofocus:Boolean,ariaLabel:String,default:String,disabled:Boolean,empty:{type:[Boolean,String],default:!0},id:[Number,String],name:[Number,String],placeholder:String,options:{type:Array,default:function(){return[]}},required:Boolean,value:{type:[String,Number,Boolean],default:""}},data:function(){var t=this;return{selected:this.value,listeners:Object(I["a"])({},this.$listeners,{click:function(e){return t.onClick(e)},change:function(e){return t.onInput(e.target.value)},input:function(t){}})}},computed:{emptyOption:function(){return this.placeholder||"—"},hasEmptyOption:function(){return!1!==this.empty&&!(this.required&&this.default)},label:function(){var t=this.text(this.selected);return""===this.selected||null===this.selected||null===t?this.emptyOption:t}},watch:{value:function(t){this.selected=t,this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$refs.input.focus()},onClick:function(t){t.stopPropagation(),this.$emit("click",t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},onInput:function(t){this.selected=t,this.$emit("input",this.selected)},select:function(){this.focus()},text:function(t){var e=null;return this.options.forEach(function(n){n.value==t&&(e=n.text)}),e}},validations:function(){return{selected:{required:!this.required||es["required"]}}}},ma=ha,ga=(n("6a18"),Object(_["a"])(ma,pa,fa,!1,null,null,null)),ba=ga.exports,va=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-draggable",{ref:"box",staticClass:"k-tags-input",attrs:{list:t.tags,"data-layout":t.layout,options:t.dragOptions},on:{end:t.onInput}},[t._l(t.tags,function(e,i){return n("k-tag",{key:i,ref:e.value,refInFor:!0,attrs:{removable:!t.disabled,name:"tag"},on:{remove:function(n){return t.remove(e)}},nativeOn:{click:function(t){t.stopPropagation()},blur:function(e){return t.selectTag(null)},focus:function(n){return t.selectTag(e)},keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"left",37,e.key,["Left","ArrowLeft"])?null:"button"in e&&0!==e.button?null:t.navigate("prev")},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"right",39,e.key,["Right","ArrowRight"])?null:"button"in e&&2!==e.button?null:t.navigate("next")}],dblclick:function(n){return t.edit(e)}}},[t._v("\n "+t._s(e.text)+"\n ")])}),n("span",{staticClass:"k-tags-input-element",attrs:{slot:"footer"},slot:"footer"},[n("k-autocomplete",{ref:"autocomplete",attrs:{options:t.options,skip:t.skip},on:{select:t.addTag,leave:function(e){return t.$refs.input.focus()}}},[n("input",{directives:[{name:"model",rawName:"v-model.trim",value:t.newTag,expression:"newTag",modifiers:{trim:!0}}],ref:"input",attrs:{autofocus:t.autofocus,disabled:t.disabled||t.max&&t.tags.length>=t.max,id:t.id,name:t.name,autocomplete:"off",type:"text"},domProps:{value:t.newTag},on:{input:[function(e){e.target.composing||(t.newTag=e.target.value.trim())},function(e){return t.type(e.target.value)}],blur:[t.blurInput,function(e){return t.$forceUpdate()}],keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"s",void 0,e.key,void 0)?null:e.metaKey?t.blurInput(e):null},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"left",37,e.key,["Left","ArrowLeft"])?null:"button"in e&&0!==e.button?null:e.ctrlKey||e.shiftKey||e.altKey||e.metaKey?null:t.leaveInput(e)},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:e.ctrlKey||e.shiftKey||e.altKey||e.metaKey?null:t.enter(e)},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"tab",9,e.key,"Tab")?null:e.ctrlKey||e.shiftKey||e.altKey||e.metaKey?null:t.tab(e)},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"backspace",void 0,e.key,void 0)?null:e.ctrlKey||e.shiftKey||e.altKey||e.metaKey?null:t.leaveInput(e)}]}})])],1)],2)},ka=[],$a={inheritAttrs:!1,props:{autofocus:Boolean,accept:{type:String,default:"all"},disabled:Boolean,icon:{type:[String,Boolean],default:"tag"},id:[Number,String],layout:String,max:Number,min:Number,name:[Number,String],options:{type:Array,default:function(){return[]}},required:Boolean,separator:{type:String,default:","},value:{type:Array,default:function(){return[]}}},data:function(){return{tags:this.prepareTags(this.value),selected:null,newTag:null,tagOptions:this.options.map(function(t){return t.icon="tag",t})}},computed:{dragOptions:function(){return{delay:1,disabled:!this.draggable,draggable:".k-tag"}},draggable:function(){return this.tags.length>1},skip:function(){return this.tags.map(function(t){return t.value})}},watch:{value:function(t){this.tags=this.prepareTags(t),this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{addString:function(t){var e=this;if(t)if(t=t.trim(),t.includes(this.separator))t.split(this.separator).forEach(function(t){e.addString(t)});else if(0!==t.length)if("options"===this.accept){var n=this.options.filter(function(e){return e.text===t})[0];if(!n)return;this.addTag(n)}else this.addTag({text:t,value:t})},addTag:function(t){this.addTagToIndex(t),this.$refs.autocomplete.close(),this.$refs.input.focus()},addTagToIndex:function(t){if("options"===this.accept){var e=this.options.filter(function(e){return e.value===t.value})[0];if(!e)return}-1===this.index(t)&&(!this.max||this.tags.length0&&(t.preventDefault(),this.addString(this.newTag))},type:function(t){this.newTag=t,this.$refs.autocomplete.search(t)}},validations:function(){return{tags:{required:!this.required||es["required"],minLength:!this.min||Object(es["minLength"])(this.min),maxLength:!this.max||Object(es["maxLength"])(this.max)}}}},_a=$a,ya=(n("27c1"),Object(_["a"])(_a,va,ka,!1,null,null,null)),xa=ya.exports,wa={extends:Is,props:Object(I["a"])({},Is.props,{autocomplete:{type:String,default:"tel"},type:{type:String,default:"tel"}})},Oa=wa,Ca=Object(_["a"])(Oa,d,p,!1,null,null,null),Sa=Ca.exports,Ea=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-textarea-input",attrs:{"data-theme":t.theme,"data-over":t.over}},[n("div",{staticClass:"k-textarea-input-wrapper"},[t.buttons&&!t.disabled?n("k-toolbar",{ref:"toolbar",attrs:{buttons:t.buttons,disabled:t.disabled,uploads:t.uploads},on:{command:t.onCommand},nativeOn:{mousedown:function(t){t.preventDefault()}}}):t._e(),n("textarea",t._b({ref:"input",staticClass:"k-textarea-input-native",attrs:{"data-font":t.font,"data-size":t.size},on:{click:t.onClick,focus:t.onFocus,input:t.onInput,keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:e.metaKey?t.onSubmit(e):null},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:e.ctrlKey?t.onSubmit(e):null},function(e){return e.metaKey?t.onShortcut(e):null},function(e){return e.ctrlKey?t.onShortcut(e):null}],dragover:t.onOver,dragleave:t.onOut,drop:t.onDrop}},"textarea",{autofocus:t.autofocus,disabled:t.disabled,id:t.id,minlength:t.minlength,name:t.name,placeholder:t.placeholder,required:t.required,spellcheck:t.spellcheck,value:t.value},!1))],1),n("k-toolbar-email-dialog",{ref:"emailDialog",on:{cancel:t.cancel,submit:function(e){return t.insert(e)}}}),n("k-toolbar-link-dialog",{ref:"linkDialog",on:{cancel:t.cancel,submit:function(e){return t.insert(e)}}}),n("k-files-dialog",{ref:"fileDialog",on:{cancel:t.cancel,submit:function(e){return t.insertFile(e)}}}),t.uploads?n("k-upload",{ref:"fileUpload",on:{success:t.insertUpload}}):t._e()],1)},ja=[],Ta={inheritAttrs:!1,props:{autofocus:Boolean,buttons:{type:[Boolean,Array],default:!0},disabled:Boolean,endpoints:Object,font:String,id:[Number,String],name:[Number,String],maxlength:Number,minlength:Number,placeholder:String,preselect:Boolean,required:Boolean,size:String,spellcheck:{type:[Boolean,String],default:"off"},theme:String,uploads:[Boolean,Object,Array],value:String},data:function(){return{over:!1}},watch:{value:function(){var t=this;this.onInvalid(),this.$nextTick(function(){t.resize()})}},mounted:function(){var t=this;this.$nextTick(function(){t.$library.autosize(t.$refs.input)}),this.onInvalid(),this.$props.autofocus&&this.focus(),this.$props.preselect&&this.select()},methods:{cancel:function(){this.$refs.input.focus()},dialog:function(t){if(!this.$refs[t+"Dialog"])throw"Invalid toolbar dialog";this.$refs[t+"Dialog"].open(this.$refs.input,this.selection())},focus:function(){this.$refs.input.focus()},insert:function(t){var e=this,n=this.$refs.input,i=n.value;setTimeout(function(){if(n.focus(),document.execCommand("insertText",!1,t),n.value===i){var s=n.value.slice(0,n.selectionStart)+t+n.value.slice(n.selectionEnd);n.value=s,e.$emit("input",s)}}),this.resize()},insertFile:function(t){t&&t.length>0&&this.insert(t.map(function(t){return t.dragText}).join("\n\n"))},insertUpload:function(t,e){this.insert(e.map(function(t){return t.dragText}).join("\n\n")),this.$events.$emit("model.update")},onClick:function(){this.$refs.toolbar&&this.$refs.toolbar.close()},onCommand:function(t,e){"function"===typeof this[t]?"function"===typeof e?this[t](e(this.$refs.input,this.selection())):this[t](e):window.console.warn(t+" is not a valid command")},onDrop:function(t){if(this.$helper.isUploadEvent(t))return this.$refs.fileUpload.drop(t.dataTransfer.files,{url:A.api+"/"+this.endpoints.field+"/upload",multiple:!1});var e=this.$store.state.drag;e&&"text"===e.type&&(this.focus(),this.insert(e.data))},onFocus:function(t){this.$emit("focus",t)},onInput:function(t){this.$emit("input",t.target.value)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},onOut:function(){this.$refs.input.blur(),this.over=!1},onOver:function(t){if(this.uploads&&this.$helper.isUploadEvent(t))return t.dataTransfer.dropEffect="copy",this.focus(),void(this.over=!0);var e=this.$store.state.drag;e&&"text"===e.type&&(t.dataTransfer.dropEffect="copy",this.focus(),this.over=!0)},onShortcut:function(t){!1!==this.buttons&&"Meta"!==t.key&&"Control"!==t.key&&this.$refs.toolbar&&this.$refs.toolbar.shortcut(t.key,t)},onSubmit:function(t){return this.$emit("submit",t)},prepend:function(t){this.insert(t+" "+this.selection())},resize:function(){this.$library.autosize.update(this.$refs.input)},select:function(){this.$refs.select()},selectFile:function(){this.$refs.fileDialog.open({endpoint:this.endpoints.field+"/files",multiple:!1})},selection:function(){var t=this.$refs.input,e=t.selectionStart,n=t.selectionEnd;return t.value.substring(e,n)},uploadFile:function(){this.$refs.fileUpload.open({url:A.api+"/"+this.endpoints.field+"/upload",multiple:!1})},wrap:function(t){this.insert(t+this.selection()+t)}},validations:function(){return{value:{required:!this.required||es["required"],minLength:!this.minlength||Object(es["minLength"])(this.minlength),maxLength:!this.maxlength||Object(es["maxLength"])(this.maxlength)}}}},Ia=Ta,La=(n("cca8"),Object(_["a"])(Ia,Ea,ja,!1,null,null,null)),qa=La.exports,Aa=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-time-input"},[n("k-select-input",{ref:"hour",attrs:{id:t.id,"aria-label":t.$t("hour"),autofocus:t.autofocus,options:t.hours,required:t.required,disabled:t.disabled,placeholder:"––"},on:{input:t.setHour,invalid:t.onInvalid},model:{value:t.hour,callback:function(e){t.hour=e},expression:"hour"}}),n("span",{staticClass:"k-time-input-separator"},[t._v(":")]),n("k-select-input",{ref:"minute",attrs:{"aria-label":t.$t("minutes"),options:t.minutes,required:t.required,disabled:t.disabled,placeholder:"––"},on:{input:t.setMinute,invalid:t.onInvalid},model:{value:t.minute,callback:function(e){t.minute=e},expression:"minute"}}),12===t.notation?n("k-select-input",{ref:"meridiem",staticClass:"k-time-input-meridiem",attrs:{"aria-label":t.$t("meridiem"),empty:!1,options:[{value:"AM",text:"AM"},{value:"PM",text:"PM"}],required:t.required,disabled:t.disabled},on:{input:t.onInput},model:{value:t.meridiem,callback:function(e){t.meridiem=e},expression:"meridiem"}}):t._e()],1)},Na=[],Ba={inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[String,Number],notation:{type:Number,default:24},required:Boolean,step:{type:Number,default:5},value:{type:String}},data:function(){var t=this.toObject(this.value);return{time:this.value,hour:t.hour,minute:t.minute,meridiem:t.meridiem}},computed:{hours:function(){return this.options(24===this.notation?0:1,24===this.notation?23:12)},minutes:function(){return this.options(0,59,this.step)}},watch:{value:function(t){this.time=t},time:function(t){var e=this.toObject(t);this.hour=e.hour,this.minute=e.minute,this.meridiem=e.meridiem}},methods:{focus:function(){this.$refs.hour.focus()},setHour:function(t){t&&!this.minute&&(this.minute=0),t||(this.minute=null),this.onInput()},setMinute:function(t){t&&!this.hour&&(this.hour=0),t||(this.hour=null),this.onInput()},onInput:function(){if(null!==this.hour&&null!==this.minute){var t=this.$helper.pad(this.hour||0),e=this.$helper.pad(this.minute||0),n=String(this.meridiem||"AM").toUpperCase(),i=24===this.notation?"".concat(t,":").concat(e,":00"):"".concat(t,":").concat(e,":00 ").concat(n),s=24===this.notation?"HH:mm:ss":"hh:mm:ss A",a=this.$library.dayjs("2000-01-01 "+i,"YYYY-MM-DD "+s);this.$emit("input",a.format("HH:mm"))}else this.$emit("input","")},onInvalid:function(t,e){this.$emit("invalid",t,e)},options:function(t,e){for(var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,i=[],s=t;s<=e;s+=n)i.push({value:s,text:this.$helper.pad(s)});return i},reset:function(){this.hour=null,this.minute=null,this.meridiem=null},round:function(t){return Math.floor(t/this.step)*this.step},toObject:function(t){var e=this.$library.dayjs("2001-01-01 "+t+":00","YYYY-MM-DD HH:mm:ss");return t&&!1!==e.isValid()?{hour:e.format(24===this.notation?"H":"h"),minute:this.round(e.format("m")),meridiem:e.format("A")}:{hour:null,minute:null,meridiem:null}}}},Pa=Ba,Da=(n("50da"),Object(_["a"])(Pa,Aa,Na,!1,null,null,null)),Ra=Da.exports,Ma=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("label",{staticClass:"k-toggle-input",attrs:{"data-disabled":t.disabled}},[n("input",{ref:"input",staticClass:"k-toggle-input-native",attrs:{disabled:t.disabled,id:t.id,type:"checkbox"},domProps:{checked:t.value},on:{change:function(e){return t.onInput(e.target.checked)}}}),n("span",{staticClass:"k-toggle-input-label",domProps:{innerHTML:t._s(t.label)}})])},za=[],Ua={inheritAttrs:!1,props:{autofocus:Boolean,disabled:Boolean,id:[Number,String],text:{type:[Array,String],default:function(){return[this.$t("off"),this.$t("on")]}},required:Boolean,value:Boolean},computed:{label:function(){return xt()(this.text)?this.value?this.text[1]:this.text[0]:this.text}},watch:{value:function(){this.onInvalid()}},mounted:function(){this.onInvalid(),this.$props.autofocus&&this.focus()},methods:{focus:function(){this.$refs.input.focus()},onEnter:function(t){"Enter"===t.key&&this.$refs.input.click()},onInput:function(t){this.$emit("input",t)},onInvalid:function(){this.$emit("invalid",this.$v.$invalid,this.$v)},select:function(){this.$refs.input.focus()}},validations:function(){return{value:{required:!this.required||es["required"]}}}},Fa=Ua,Ha=(n("bb41"),Object(_["a"])(Fa,Ma,za,!1,null,null,null)),Ka=Ha.exports,Va={extends:Is,props:Object(I["a"])({},Is.props,{autocomplete:{type:String,default:"url"},type:{type:String,default:"url"}})},Ya=Va,Wa=Object(_["a"])(Ya,f,h,!1,null,null,null),Ga=Wa.exports,Ja=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-checkboxes-field",attrs:{counter:t.counterOptions}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},Za=[],Xa={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,ds.props,{counter:{type:Boolean,default:!0}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value&&xt()(this.value)?this.value.length:0,min:this.min,max:this.max}}},methods:{focus:function(){this.$refs.input.focus()}}},Qa=Xa,to=Object(_["a"])(Qa,Ja,Za,!1,null,null,null),eo=to.exports,no=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-date-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,type:t.inputType,value:t.date,theme:"field"}},"k-input",t.$props,!1),t.listeners),[n("template",{slot:"icon"},[n("k-dropdown",[n("k-button",{staticClass:"k-input-icon-button",attrs:{icon:t.icon,tooltip:t.$t("date.select"),tabindex:"-1"},on:{click:function(e){return t.$refs.dropdown.toggle()}}}),n("k-dropdown-content",{ref:"dropdown",attrs:{align:"right"}},[n("k-calendar",{attrs:{value:t.date},on:{input:function(e){t.onInput(e),t.$refs.dropdown.close()}}})],1)],1)],1)],2)],1)},io=[],so={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,Os.props,{icon:{type:String,default:"calendar"}}),data:function(){return{date:this.value,listeners:Object(I["a"])({},this.$listeners,{input:this.onInput})}},computed:{inputType:function(){return!1===this.time?"date":"datetime"}},watch:{value:function(t){this.date=t}},methods:{focus:function(){this.$refs.input.focus()},onInput:function(t){this.date=t,this.$emit("input",t)}}},ao=so,oo=Object(_["a"])(ao,no,io,!1,null,null,null),ro=oo.exports,lo=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-email-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners),[t.link?n("k-button",{staticClass:"k-input-icon-button",attrs:{slot:"icon",icon:t.icon,link:"mailto:"+t.value,tooltip:t.$t("open"),tabindex:"-1",target:"_blank"},slot:"icon"}):t._e()],1)],1)},uo=[],co={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,Ns.props,{link:{type:Boolean,default:!0},icon:{type:String,default:"email"}}),methods:{focus:function(){this.$refs.input.focus()}}},po=co,fo=Object(_["a"])(po,lo,uo,!1,null,null,null),ho=fo.exports,mo=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-files-field"},"k-field",t.$props,!1),[t.more&&!t.disabled?n("template",{slot:"options"},[n("k-button-group",{staticClass:"k-field-options"},[t.uploads?[n("k-dropdown",[n("k-button",{ref:"pickerToggle",staticClass:"k-field-options-button",attrs:{icon:"add"},on:{click:function(e){return t.$refs.picker.toggle()}}},[t._v("\n "+t._s(t.$t("add"))+"\n ")]),n("k-dropdown-content",{ref:"picker",attrs:{align:"right"}},[n("k-dropdown-item",{attrs:{icon:"check"},on:{click:t.open}},[t._v(t._s(t.$t("select")))]),n("k-dropdown-item",{attrs:{icon:"upload"},on:{click:t.upload}},[t._v(t._s(t.$t("upload")))])],1)],1)]:[n("k-button",{staticClass:"k-field-options-button",attrs:{icon:"add"},on:{click:t.open}},[t._v(t._s(t.$t("add")))])]],2)],1):t._e(),t.selected.length?[n("k-draggable",{attrs:{element:t.elements.list,list:t.selected,"data-size":t.size,handle:!0,"data-invalid":t.isInvalid},on:{end:t.onInput}},t._l(t.selected,function(e,i){return n(t.elements.item,{key:e.filename,tag:"component",attrs:{sortable:!t.disabled&&t.selected.length>1,text:e.text,link:e.link,info:e.info,image:e.image,icon:e.icon}},[t.disabled?t._e():n("k-button",{attrs:{slot:"options",tooltip:t.$t("remove"),icon:"remove"},on:{click:function(e){return t.remove(i)}},slot:"options"})],1)}),1)]:n("k-empty",{attrs:{layout:t.layout,"data-invalid":t.isInvalid,icon:"image"},on:{click:t.open}},[t._v("\n "+t._s(t.empty||t.$t("field.files.empty"))+"\n ")]),n("k-files-dialog",{ref:"selector",on:{submit:t.select}}),n("k-upload",{ref:"fileUpload",on:{success:t.selectUpload}})],2)},go=[],bo={inheritAttrs:!1,props:Object(I["a"])({},Li.props,{empty:String,info:String,layout:String,max:Number,multiple:Boolean,parent:String,search:Boolean,size:String,text:String,value:{type:Array,default:function(){return[]}}}),data:function(){return{selected:this.value}},computed:{elements:function(){var t={cards:{list:"k-cards",item:"k-card"},list:{list:"k-list",item:"k-list-item"}};return t[this.layout]?t[this.layout]:t["list"]},isInvalid:function(){return!(!this.required||0!==this.selected.length)||(!!(this.min&&this.selected.lengththis.max))},more:function(){return!this.max||this.max>this.selected.length}},watch:{value:function(t){this.selected=t}},methods:{focus:function(){},onInput:function(){this.$emit("input",this.selected)},remove:function(t){this.selected.splice(t,1),this.onInput()},removeById:function(t){this.selected=this.selected.filter(function(e){return e.id!==t}),this.onInput()},select:function(t){var e=this;0!==t.length?(this.selected=this.selected.filter(function(e){return t.filter(function(t){return t.id===e.id}).length>0}),t.forEach(function(t){0===e.selected.filter(function(e){return t.id===e.id}).length&&e.selected.push(t)}),this.onInput()):this.selected=[]}}},vo={mixins:[bo],props:{uploads:[Boolean,Object,Array]},created:function(){this.$events.$on("file.delete",this.removeById)},destroyed:function(){this.$events.$off("file.delete",this.removeById)},methods:{prompt:function(t){t.stopPropagation(),this.uploads?this.$refs.picker.toggle():this.open()},open:function(){if(this.disabled)return!1;this.$refs.selector.open({endpoint:this.endpoints.field,max:this.max,multiple:this.multiple,search:this.search,selected:this.selected.map(function(t){return t.id})})},selectUpload:function(t,e){var n=this;!1===this.multiple&&(this.selected=[]),e.forEach(function(t){n.selected.push(t)}),this.onInput(),this.$events.$emit("model.update")},upload:function(){this.$refs.fileUpload.open({url:A.api+"/"+this.endpoints.field+"/upload",multiple:this.multiple,accept:this.uploads.accept})}}},ko=vo,$o=(n("4a4b"),Object(_["a"])(ko,mo,go,!1,null,null,null)),_o=$o.exports,yo=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-headline",{staticClass:"k-headline-field",attrs:{"data-numbered":t.numbered,size:"large"}},[t._v("\n "+t._s(t.label)+"\n")])},xo=[],wo={props:{label:String,numbered:Boolean}},Oo=wo,Co=(n("19d7"),Object(_["a"])(Oo,yo,xo,!1,null,null,null)),So=Co.exports,Eo=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-field k-info-field"},[n("k-headline",[t._v(t._s(t.label))]),n("k-box",{attrs:{theme:t.theme}},[n("k-text",{domProps:{innerHTML:t._s(t.text)}})],1)],1)},jo=[],To={props:{label:String,text:String,theme:{type:String,default:"info"}}},Io=To,Lo=(n("ddfd"),Object(_["a"])(Io,Eo,jo,!1,null,null,null)),qo=Lo.exports,Ao=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("hr",{staticClass:"k-line-field"})},No=[],Bo=(n("718c"),{}),Po=Object(_["a"])(Bo,Ao,No,!1,null,null,null),Do=Po.exports,Ro=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-multiselect-field",attrs:{input:t._uid,counter:t.counterOptions},on:{blur:t.blur},nativeOn:{keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:(e.preventDefault(),t.focus(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"space",32,e.key,[" ","Spacebar"])?null:(e.preventDefault(),t.focus(e))}]}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},Mo=[],zo={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,zs.props,{counter:{type:Boolean,default:!0},icon:{type:String,default:"angle-down"}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value&&xt()(this.value)?this.value.length:0,min:this.min,max:this.max}}},mounted:function(){this.$refs.input.$el.setAttribute("tabindex",0)},methods:{blur:function(t){this.$refs.input.blur(t)},focus:function(){this.$refs.input.focus()}}},Uo=zo,Fo=Object(_["a"])(Uo,Ro,Mo,!1,null,null,null),Ho=Fo.exports,Ko=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-number-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},Vo=[],Yo={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,Gs.props),methods:{focus:function(){this.$refs.input.focus()}}},Wo=Yo,Go=Object(_["a"])(Wo,Ko,Vo,!1,null,null,null),Jo=Go.exports,Zo=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-pages-field"},"k-field",t.$props,!1),[n("k-button-group",{staticClass:"k-field-options",attrs:{slot:"options"},slot:"options"},[t.more&&!t.disabled?n("k-button",{staticClass:"k-field-options-button",attrs:{icon:"add"},on:{click:t.open}},[t._v("\n "+t._s(t.$t("select"))+"\n ")]):t._e()],1),t.selected.length?[n("k-draggable",{attrs:{element:t.elements.list,handle:!0,list:t.selected,"data-size":t.size,"data-invalid":t.isInvalid},on:{end:t.onInput}},t._l(t.selected,function(e,i){return n(t.elements.item,{key:e.id,tag:"component",attrs:{sortable:!t.disabled&&t.selected.length>1,text:e.text,info:e.info,link:e.link,icon:e.icon,image:e.image}},[t.disabled?t._e():n("k-button",{attrs:{slot:"options",icon:"remove"},on:{click:function(e){return t.remove(i)}},slot:"options"})],1)}),1)]:n("k-empty",{attrs:{layout:t.layout,"data-invalid":t.isInvalid,icon:"page"},on:{click:t.open}},[t._v("\n "+t._s(t.empty||t.$t("field.pages.empty"))+"\n ")]),n("k-pages-dialog",{ref:"selector",on:{submit:t.select}})],2)},Xo=[],Qo={mixins:[bo],methods:{open:function(){if(this.disabled)return!1;this.$refs.selector.open({endpoint:this.endpoints.field,max:this.max,multiple:this.multiple,search:this.search,selected:this.selected.map(function(t){return t.id})})}}},tr=Qo,er=(n("7e85"),Object(_["a"])(tr,Zo,Xo,!1,null,null,null)),nr=er.exports,ir=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-password-field",attrs:{input:t._uid,counter:t.counterOptions}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},sr=[],ar={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,Qs.props,{counter:{type:Boolean,default:!0},minlength:{type:Number,default:8},icon:{type:String,default:"key"}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value?String(this.value).length:0,min:this.minlength,max:this.maxlength}}},methods:{focus:function(){this.$refs.input.focus()}}},or=ar,rr=Object(_["a"])(or,ir,sr,!1,null,null,null),lr=rr.exports,ur=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-radio-field"},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},cr=[],dr={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,aa.props),methods:{focus:function(){this.$refs.input.focus()}}},pr=dr,fr=Object(_["a"])(pr,ur,cr,!1,null,null,null),hr=fr.exports,mr=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-range-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},gr=[],br={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,da.props),methods:{focus:function(){this.$refs.input.focus()}}},vr=br,kr=Object(_["a"])(vr,mr,gr,!1,null,null,null),$r=kr.exports,_r=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-select-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},yr=[],xr={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,ba.props,{icon:{type:String,default:"angle-down"}}),methods:{focus:function(){this.$refs.input.focus()}}},wr=xr,Or=Object(_["a"])(wr,_r,yr,!1,null,null,null),Cr=Or.exports,Sr=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-structure-field",nativeOn:{click:function(t){t.stopPropagation()}}},"k-field",t.$props,!1),[n("template",{slot:"options"},[t.more&&null===t.currentIndex?n("k-button",{ref:"add",attrs:{id:t._uid,icon:"add"},on:{click:t.add}},[t._v("\n "+t._s(t.$t("add"))+"\n ")]):t._e()],1),null!==t.currentIndex?[n("div",{staticClass:"k-structure-backdrop",on:{click:t.escape}}),n("section",{staticClass:"k-structure-form"},[n("k-form",{ref:"form",staticClass:"k-structure-form-fields",attrs:{fields:t.formFields},on:{input:t.onInput,submit:t.submit},model:{value:t.currentModel,callback:function(e){t.currentModel=e},expression:"currentModel"}}),n("footer",{staticClass:"k-structure-form-buttons"},[n("k-button",{staticClass:"k-structure-form-cancel-button",attrs:{icon:"cancel"},on:{click:t.close}},[t._v(t._s(t.$t("cancel")))]),"new"!==t.currentIndex?n("k-pagination",{attrs:{dropdown:!1,total:t.items.length,limit:1,page:t.currentIndex+1,details:!0,validate:t.beforePaginate},on:{paginate:t.paginate}}):t._e(),n("k-button",{staticClass:"k-structure-form-submit-button",attrs:{icon:"check"},on:{click:t.submit}},[t._v(t._s(t.$t("new"!==t.currentIndex?"confirm":"add")))])],1)],1)]:0===t.items.length?n("k-empty",{attrs:{"data-invalid":t.isInvalid,icon:"list-bullet"},on:{click:t.add}},[t._v("\n "+t._s(t.empty||t.$t("field.structure.empty"))+"\n ")]):[n("table",{staticClass:"k-structure-table",attrs:{"data-invalid":t.isInvalid,"data-sortable":t.isSortable}},[n("thead",[n("tr",[n("th",{staticClass:"k-structure-table-index"},[t._v("#")]),t._l(t.columns,function(e,i){return n("th",{key:i+"-header",staticClass:"k-structure-table-column",style:"width:"+t.width(e.width),attrs:{"data-align":e.align}},[t._v("\n "+t._s(e.label)+"\n ")])}),n("th")],2)]),n("k-draggable",{attrs:{list:t.items,"data-disabled":t.disabled,options:t.dragOptions,handle:!0,element:"tbody"},on:{end:t.onInput}},t._l(t.paginatedItems,function(e,i){return n("tr",{key:i,on:{click:function(t){t.stopPropagation()}}},[n("td",{staticClass:"k-structure-table-index"},[t.isSortable?n("k-sort-handle"):t._e(),n("span",{staticClass:"k-structure-table-index-number"},[t._v(t._s(t.indexOf(i)))])],1),t._l(t.columns,function(s,a){return n("td",{key:a,staticClass:"k-structure-table-column",style:"width:"+t.width(s.width),attrs:{title:s.label,"data-align":s.align},on:{click:function(e){return t.jump(i,a)}}},[!1===t.columnIsEmpty(e[a])?[t.previewExists(s.type)?n("k-"+s.type+"-field-preview",{tag:"component",attrs:{value:e[a],column:s,field:t.fields[a]},on:{input:function(e){return t.update(i,a,e)}}}):[n("p",{staticClass:"k-structure-table-text"},[t._v("\n "+t._s(s.before)+" "+t._s(t.displayText(t.fields[a],e[a])||"–")+" "+t._s(s.after)+"\n ")])]]:t._e()],2)}),n("td",{staticClass:"k-structure-table-option"},[n("k-button",{attrs:{tooltip:t.$t("remove"),icon:"remove"},on:{click:function(e){return t.confirmRemove(i)}}})],1)],2)}),0)],1),t.limit?n("k-pagination",t._b({on:{paginate:t.paginateItems}},"k-pagination",t.pagination,!1)):t._e(),t.disabled?t._e():n("k-dialog",{ref:"remove",attrs:{button:t.$t("delete"),theme:"negative"},on:{submit:t.remove}},[n("k-text",[t._v(t._s(t.$t("field.structure.delete.confirm")))])],1)]],2)},Er=[];Array.prototype.sortBy=function(t){var e=this,n=t.split(" "),i=n[0],s=n[1]||"asc";return this.sort(function(t,n){var a=String(t[i]).toLowerCase(),o=String(n[i]).toLowerCase();return"desc"===s?e.$helper.sort(o,a):e.$helper.sort(a,o)})};var jr,Tr,Ir,Lr,qr={inheritAttrs:!1,props:Object(I["a"])({},Li.props,{columns:Object,empty:String,fields:Object,limit:Number,max:Number,min:Number,sortable:{type:Boolean,default:!0},sortBy:String,value:{type:Array,default:function(){return[]}}}),data:function(){return{items:this.makeItems(this.value),currentIndex:null,currentModel:null,trash:null,page:1}},computed:{dragOptions:function(){return{disabled:!this.isSortable,fallbackClass:"k-sortable-row-fallback"}},formFields:function(){var t=this,e={};return kt()(this.fields).forEach(function(n){var i=t.fields[n];i.section=t.name,i.endpoints={field:t.endpoints.field+"+"+n,section:t.endpoints.section,model:t.endpoints.model},e[n]=i}),e},more:function(){return!0!==this.disabled&&!(this.max&&this.items.length>=this.max)},isInvalid:function(){return!0!==this.disabled&&(!!(this.min&&this.items.lengththis.max))},isSortable:function(){return!this.sortBy&&(!this.limit&&(!0!==this.disabled&&(!(this.items.length<=1)&&!1!==this.sortable)))},pagination:function(){var t=0;return this.limit&&(t=(this.page-1)*this.limit),{page:this.page,offset:t,limit:this.limit,total:this.items.length,align:"center",details:!0}},paginatedItems:function(){return this.limit?this.items.slice(this.pagination.offset,this.pagination.offset+this.limit):this.items}},watch:{value:function(t){t!=this.items&&(this.items=this.makeItems(t))}},methods:{add:function(){var t=this;if(!0===this.disabled)return!1;if(null!==this.currentIndex)return this.escape(),!1;var e={};kt()(this.fields).forEach(function(n){var i=t.fields[n];null!==i.default?e[n]=t.$helper.clone(i.default):e[n]=null}),this.currentIndex="new",this.currentModel=e,this.createForm()},close:function(){this.currentIndex=null,this.currentModel=null,this.$events.$off("keydown.esc",this.escape),this.$events.$off("keydown.cmd.s",this.submit),this.$store.dispatch("content/enable")},columnIsEmpty:function(t){return void 0===t||null===t||""===t||("object"===Object(Ht["a"])(t)&&0===kt()(t).length&&t.constructor===Object||void 0!==t.length&&0===t.length)},confirmRemove:function(t){this.close(),this.trash=t,this.$refs.remove.open()},createForm:function(t){var e=this;this.$events.$on("keydown.esc",this.escape),this.$events.$on("keydown.cmd.s",this.submit),this.$store.dispatch("content/disable"),this.$nextTick(function(){e.$refs.form&&e.$refs.form.focus(t)})},displayText:function(t,e){switch(t.type){case"user":return e.email;case"date":var n=this.$library.dayjs(e),i=!0===t.time?"YYYY-MM-DD HH:mm":"YYYY-MM-DD";return n.isValid()?n.format(i):"";case"tags":case"multiselect":return e.map(function(t){return t.text}).join(", ");case"checkboxes":return e.map(function(e){var n=e;return t.options.forEach(function(t){t.value===e&&(n=t.text)}),n}).join(", ");case"radio":case"select":var s=t.options.filter(function(t){return t.value===e})[0];return s?s.text:null}return"object"===Object(Ht["a"])(e)&&null!==e?"…":e},escape:function(){var t=this;if("new"===this.currentIndex){var e=_t()(this.currentModel),n=!0;if(e.forEach(function(e){!1===t.columnIsEmpty(e)&&(n=!1)}),!0===n)return void this.close()}this.submit()},focus:function(){this.$refs.add&&this.$refs.add.focus&&this.$refs.add.focus()},indexOf:function(t){return this.limit?(this.page-1)*this.limit+t+1:t+1},isActive:function(t){return this.currentIndex===t},jump:function(t,e){this.open(t+this.pagination.offset,e)},makeItems:function(t){return!1===xt()(t)?[]:this.sort(t)},onInput:function(){this.$emit("input",this.items)},open:function(t,e){this.currentIndex=t,this.currentModel=this.$helper.clone(this.items[t]),this.createForm(e)},beforePaginate:function(){return this.save(this.currentModel)},paginate:function(t){this.open(t.offset)},paginateItems:function(t){this.page=t.page},previewExists:function(t){return void 0!==z["a"].options.components["k-"+t+"-field-preview"]||void 0!==this.$options.components["k-"+t+"-field-preview"]},remove:function(){if(null===this.trash)return!1;this.items.splice(this.trash,1),this.trash=null,this.$refs.remove.close(),this.onInput(),0===this.paginatedItems.length&&this.page>1&&this.page--,this.items=this.sort(this.items)},sort:function(t){return this.sortBy?t.sortBy(this.sortBy):t},save:function(){var t=this;return null!==this.currentIndex&&void 0!==this.currentIndex?this.validate(this.currentModel).then(function(){return"new"===t.currentIndex?t.items.push(t.currentModel):t.items[t.currentIndex]=t.currentModel,t.items=t.sort(t.items),t.onInput(),!0}).catch(function(e){throw t.$store.dispatch("notification/error",{message:t.$t("error.form.incomplete"),details:e}),e}):Je.a.resolve()},submit:function(){this.save().then(this.close).catch(function(){})},validate:function(t){return this.$api.post(this.endpoints.field+"/validate",t).then(function(t){if(t.length>0)throw t;return!0})},width:function(t){if(!t)return"auto";var e=t.toString().split("/");if(2!==e.length)return"auto";var n=Number(e[0]),i=Number(e[1]);return Ks()(100/i*n,2).toFixed(2)+"%"},update:function(t,e,n){this.items[t][e]=n,this.onInput()}}},Ar=qr,Nr=(n("088c"),Object(_["a"])(Ar,Sr,Er,!1,null,null,null)),Br=Nr.exports,Pr=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-tags-field",attrs:{input:t._uid,counter:t.counterOptions}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},Dr=[],Rr={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,xa.props,{counter:{type:Boolean,default:!0}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value&&xt()(this.value)?this.value.length:0,min:this.min,max:this.max}}},methods:{focus:function(){this.$refs.input.focus()}}},Mr=Rr,zr=Object(_["a"])(Mr,Pr,Dr,!1,null,null,null),Ur=zr.exports,Fr=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-tel-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},Hr=[],Kr={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,Sa.props,{icon:{type:String,default:"phone"}}),methods:{focus:function(){this.$refs.input.focus()}}},Vr=Kr,Yr=Object(_["a"])(Vr,Fr,Hr,!1,null,null,null),Wr=Yr.exports,Gr=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-text-field",attrs:{input:t._uid,counter:t.counterOptions}},"k-field",t.$props,!1),[t._t("options",null,{slot:"options"}),n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],2)},Jr=[],Zr={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,Is.props,{counter:{type:Boolean,default:!0}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value?String(this.value).length:0,min:this.minlength,max:this.maxlength}}},methods:{focus:function(){this.$refs.input.focus()}}},Xr=Zr,Qr=(n("b746"),Object(_["a"])(Xr,Gr,Jr,!1,null,null,null)),tl=Qr.exports,el=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-textarea-field",attrs:{input:t._uid,counter:t.counterOptions}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,type:"textarea",theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},nl=[],il={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,qa.props,{counter:{type:Boolean,default:!0}}),computed:{counterOptions:function(){return null!==this.value&&!this.disabled&&!1!==this.counter&&{count:this.value?this.value.length:0,min:this.minlength,max:this.maxlength}}},methods:{focus:function(){this.$refs.input.focus()}}},sl=il,al=Object(_["a"])(sl,el,nl,!1,null,null,null),ol=al.exports,rl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-time-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},ll=[],ul={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,Ra.props,{icon:{type:String,default:"clock"}}),methods:{focus:function(){this.$refs.input.focus()}}},cl=ul,dl=Object(_["a"])(cl,rl,ll,!1,null,null,null),pl=dl.exports,fl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-toggle-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners))],1)},hl=[],ml={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,Ka.props),methods:{focus:function(){this.$refs.input.focus()}}},gl=ml,bl=Object(_["a"])(gl,fl,hl,!1,null,null,null),vl=bl.exports,kl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-url-field",attrs:{input:t._uid}},"k-field",t.$props,!1),[n("k-input",t._g(t._b({ref:"input",attrs:{id:t._uid,theme:"field"}},"k-input",t.$props,!1),t.$listeners),[t.link?n("k-button",{staticClass:"k-input-icon-button",attrs:{slot:"icon",icon:t.icon,link:t.value,tooltip:t.$t("open"),tabindex:"-1",target:"_blank"},slot:"icon"}):t._e()],1)],1)},$l=[],_l={inheritAttrs:!1,props:Object(I["a"])({},Li.props,Hi.props,Ga.props,{link:{type:Boolean,default:!0},icon:{type:String,default:"url"}}),methods:{focus:function(){this.$refs.input.focus()}}},yl=_l,xl=Object(_["a"])(yl,kl,$l,!1,null,null,null),wl=xl.exports,Ol=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-field",t._b({staticClass:"k-users-field"},"k-field",t.$props,!1),[n("k-button-group",{staticClass:"k-field-options",attrs:{slot:"options"},slot:"options"},[t.more&&!t.disabled?n("k-button",{staticClass:"k-field-options-button",attrs:{icon:"add"},on:{click:t.open}},[t._v("\n "+t._s(t.$t("select"))+"\n ")]):t._e()],1),t.selected.length?[n("k-draggable",{attrs:{element:t.elements.list,list:t.selected,handle:!0,"data-invalid":t.isInvalid},on:{end:t.onInput}},t._l(t.selected,function(e,i){return n(t.elements.item,{key:e.email,tag:"component",attrs:{sortable:!t.disabled&&t.selected.length>1,text:e.username,info:e.info,link:t.$api.users.link(e.id),image:e.image,icon:e.icon}},[t.disabled?t._e():n("k-button",{attrs:{slot:"options",icon:"remove"},on:{click:function(e){return t.remove(i)}},slot:"options"})],1)}),1)]:n("k-empty",{attrs:{"data-invalid":t.isInvalid,icon:"users"},on:{click:t.open}},[t._v("\n "+t._s(t.empty||t.$t("field.users.empty"))+"\n ")]),n("k-users-dialog",{ref:"selector",on:{submit:t.select}})],2)},Cl=[],Sl={mixins:[bo],methods:{open:function(){if(this.disabled)return!1;this.$refs.selector.open({endpoint:this.endpoints.field,max:this.max,multiple:this.multiple,search:this.search,selected:this.selected.map(function(t){return t.id})})}}},El=Sl,jl=(n("7f6e"),Object(_["a"])(El,Ol,Cl,!1,null,null,null)),Tl=jl.exports,Il=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("nav",{staticClass:"k-toolbar"},[n("div",{staticClass:"k-toolbar-wrapper"},[n("div",{staticClass:"k-toolbar-buttons"},[t._l(t.layout,function(e,i){return[e.divider?[n("span",{key:i,staticClass:"k-toolbar-divider"})]:e.dropdown?[n("k-dropdown",{key:i},[n("k-button",{key:i,staticClass:"k-toolbar-button",attrs:{icon:e.icon,tooltip:e.label,tabindex:"-1"},on:{click:function(e){t.$refs[i+"-dropdown"][0].toggle()}}}),n("k-dropdown-content",{ref:i+"-dropdown",refInFor:!0},t._l(e.dropdown,function(e,i){return n("k-dropdown-item",{key:i,attrs:{icon:e.icon},on:{click:function(n){return t.command(e.command,e.args)}}},[t._v("\n "+t._s(e.label)+"\n ")])}),1)],1)]:[n("k-button",{key:i,staticClass:"k-toolbar-button",attrs:{icon:e.icon,tooltip:e.label,tabindex:"-1"},on:{click:function(n){return t.command(e.command,e.args)}}})]]})],2)])])},Ll=[],ql=function(t){this.command("insert",function(e,n){var i=[];return n.split("\n").forEach(function(e,n){var s="ol"===t?n+1+".":"-";i.push(s+" "+e)}),i.join("\n")})},Al={layout:["headlines","bold","italic","|","link","email","file","|","code","ul","ol"],props:{buttons:{type:[Boolean,Array],default:!0},uploads:[Boolean,Object,Array]},data:function(){var t={},e={},n=[],i=this.commands();return!1===this.buttons?t:(xt()(this.buttons)&&(n=this.buttons),!0!==xt()(this.buttons)&&(n=this.$options.layout),n.forEach(function(n,s){if("|"===n)t["divider-"+s]={divider:!0};else if(i[n]){var a=i[n];t[n]=a,a.shortcut&&(e[a.shortcut]=n)}}),{layout:t,shortcuts:e})},methods:{command:function(t,e){"function"===typeof t?t.apply(this):this.$emit("command",t,e)},close:function(){var t=this;kt()(this.$refs).forEach(function(e){var n=t.$refs[e][0];n.close&&"function"===typeof n.close&&n.close()})},fileCommandSetup:function(){var t={label:this.$t("toolbar.button.file"),icon:"attachment"};return!1===this.uploads?t.command="selectFile":t.dropdown={select:{label:this.$t("toolbar.button.file.select"),icon:"check",command:"selectFile"},upload:{label:this.$t("toolbar.button.file.upload"),icon:"upload",command:"uploadFile"}},t},commands:function(){return{headlines:{label:this.$t("toolbar.button.headings"),icon:"title",dropdown:{h1:{label:this.$t("toolbar.button.heading.1"),icon:"title",command:"prepend",args:"#"},h2:{label:this.$t("toolbar.button.heading.2"),icon:"title",command:"prepend",args:"##"},h3:{label:this.$t("toolbar.button.heading.3"),icon:"title",command:"prepend",args:"###"}}},bold:{label:this.$t("toolbar.button.bold"),icon:"bold",command:"wrap",args:"**",shortcut:"b"},italic:{label:this.$t("toolbar.button.italic"),icon:"italic",command:"wrap",args:"*",shortcut:"i"},link:{label:this.$t("toolbar.button.link"),icon:"url",shortcut:"l",command:"dialog",args:"link"},email:{label:this.$t("toolbar.button.email"),icon:"email",shortcut:"e",command:"dialog",args:"email"},file:this.fileCommandSetup(),code:{label:this.$t("toolbar.button.code"),icon:"code",command:"wrap",args:"`"},ul:{label:this.$t("toolbar.button.ul"),icon:"list-bullet",command:function(){return ql.apply(this,["ul"])}},ol:{label:this.$t("toolbar.button.ol"),icon:"list-numbers",command:function(){return ql.apply(this,["ol"])}}}},shortcut:function(t,e){if(this.shortcuts[t]){var n=this.layout[this.shortcuts[t]];if(!n)return!1;e.preventDefault(),this.command(n.command,n.args)}}}},Nl=Al,Bl=(n("df0d"),Object(_["a"])(Nl,Il,Ll,!1,null,null,null)),Pl=Bl.exports,Dl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("insert")},on:{close:t.cancel,submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.value,callback:function(e){t.value=e},expression:"value"}})],1)},Rl=[],Ml={data:function(){return{value:{email:null,text:null},fields:{email:{label:this.$t("email"),type:"email"},text:{label:this.$t("link.text"),type:"text"}}}},computed:{kirbytext:function(){return this.$store.state.system.info.kirbytext}},methods:{open:function(t,e){this.value.text=e,this.$refs.dialog.open()},cancel:function(){this.$emit("cancel")},createKirbytext:function(){var t=this.value.email||"";return this.value.text&&this.value.text.length>0?"(email: ".concat(t," text: ").concat(this.value.text,")"):"(email: ".concat(t,")")},createMarkdown:function(){var t=this.value.email||"";return this.value.text&&this.value.text.length>0?"[".concat(this.value.text,"](mailto:").concat(t,")"):"<".concat(t,">")},submit:function(){this.$emit("submit",this.kirbytext?this.createKirbytext():this.createMarkdown()),this.value={email:null,text:null},this.$refs.dialog.close()}}},zl=Ml,Ul=Object(_["a"])(zl,Dl,Rl,!1,null,null,null),Fl=Ul.exports,Hl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-dialog",{ref:"dialog",attrs:{button:t.$t("insert")},on:{close:t.cancel,submit:function(e){return t.$refs.form.submit()}}},[n("k-form",{ref:"form",attrs:{fields:t.fields},on:{submit:t.submit},model:{value:t.value,callback:function(e){t.value=e},expression:"value"}})],1)},Kl=[],Vl={data:function(){return{value:{url:null,text:null},fields:{url:{label:this.$t("link"),type:"text",placeholder:this.$t("url.placeholder"),icon:"url"},text:{label:this.$t("link.text"),type:"text"}}}},computed:{kirbytext:function(){return this.$store.state.system.info.kirbytext}},methods:{open:function(t,e){this.value.text=e,this.$refs.dialog.open()},cancel:function(){this.$emit("cancel")},createKirbytext:function(){return this.value.text.length>0?"(link: ".concat(this.value.url," text: ").concat(this.value.text,")"):"(link: ".concat(this.value.url,")")},createMarkdown:function(){return this.value.text.length>0?"[".concat(this.value.text,"](").concat(this.value.url,")"):"<".concat(this.value.url,">")},submit:function(){this.$emit("submit",this.kirbytext?this.createKirbytext():this.createMarkdown()),this.value={url:null,text:null},this.$refs.dialog.close()}}},Yl=Vl,Wl=Object(_["a"])(Yl,Hl,Kl,!1,null,null,null),Gl=Wl.exports,Jl=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.value?n("ul",{staticClass:"k-files-field-preview"},t._l(t.value,function(e){return n("li",{key:e.url},[n("k-link",{attrs:{title:e.filename,to:e.link},nativeOn:{click:function(t){t.stopPropagation()}}},["image"===e.type?n("k-image",t._b({},"k-image",t.imageOptions(e),!1)):n("k-icon",t._b({},"k-icon",e.icon,!1))],1)],1)}),0):t._e()},Zl=[],Xl=function(t){if(!t)return!1;var e=null,n=null;return t.list?(e=t.list.url,n=t.list.srcset):(e=t.url,n=t.srcset),!!e&&{src:e,srcset:n,back:t.back||"black",cover:t.cover}},Ql={props:{value:Array,field:Object},methods:{imageOptions:function(t){var e=Xl(t.image);return e.src?Object(I["a"])({},e,{back:"pattern",cover:!1},this.field.image||{}):{src:t.url}}}},tu=Ql,eu=(n("21dc"),Object(_["a"])(tu,Jl,Zl,!1,null,null,null)),nu=eu.exports,iu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("p",{staticClass:"k-url-field-preview"},[t._v("\n "+t._s(t.column.before)+"\n "),n("k-link",{attrs:{to:t.link,target:"_blank"},nativeOn:{click:function(t){t.stopPropagation()}}},[t._v(t._s(t.value))]),t._v("\n "+t._s(t.column.after)+"\n")],1)},su=[],au={props:{column:{type:Object,default:function(){return{}}},value:String},computed:{link:function(){return this.value}}},ou=au,ru=(n("977f"),Object(_["a"])(ou,iu,su,!1,null,null,null)),lu=ru.exports,uu={extends:lu,computed:{link:function(){return"mailto:"+this.value}}},cu=uu,du=Object(_["a"])(cu,jr,Tr,!1,null,null,null),pu=du.exports,fu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.value?n("ul",{staticClass:"k-pages-field-preview"},t._l(t.value,function(e){return n("li",{key:e.id},[n("figure",[n("k-link",{attrs:{title:e.id,to:t.$api.pages.link(e.id)},nativeOn:{click:function(t){t.stopPropagation()}}},[n("k-icon",{staticClass:"k-pages-field-preview-image",attrs:{type:"page",back:"pattern"}}),n("figcaption",[t._v("\n "+t._s(e.text)+"\n ")])],1)],1)])}),0):t._e()},hu=[],mu={props:{value:Array}},gu=mu,bu=(n("d0c1"),Object(_["a"])(gu,fu,hu,!1,null,null,null)),vu=bu.exports,ku=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-input",{staticClass:"k-toggle-field-preview",attrs:{text:t.text,type:"toggle"},on:{input:function(e){return t.$emit("input",e)}},model:{value:t.value,callback:function(e){t.value=e},expression:"value"}})},$u=[],_u={props:{field:Object,value:Boolean,column:Object},computed:{text:function(){return!1!==this.column.text?this.field.text:null}}},yu=_u,xu=(n("1c4e"),Object(_["a"])(yu,ku,$u,!1,null,null,null)),wu=xu.exports,Ou=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.value?n("ul",{staticClass:"k-users-field-preview"},t._l(t.value,function(e){return n("li",{key:e.email},[n("figure",[n("k-link",{attrs:{title:e.email,to:t.$api.users.link(e.id)},nativeOn:{click:function(t){t.stopPropagation()}}},[e.avatar?n("k-image",{staticClass:"k-users-field-preview-avatar",attrs:{src:e.avatar.url,back:"pattern"}}):n("k-icon",{staticClass:"k-users-field-preview-avatar",attrs:{type:"user",back:"pattern"}}),n("figcaption",[t._v("\n "+t._s(e.username)+"\n ")])],1)],1)])}),0):t._e()},Cu=[],Su={props:{value:Array}},Eu=Su,ju=(n("3a85"),Object(_["a"])(Eu,Ou,Cu,!1,null,null,null)),Tu=ju.exports,Iu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-bar"},[t.$slots.left?n("div",{staticClass:"k-bar-slot",attrs:{"data-position":"left"}},[t._t("left")],2):t._e(),t.$slots.center?n("div",{staticClass:"k-bar-slot",attrs:{"data-position":"center"}},[t._t("center")],2):t._e(),t.$slots.right?n("div",{staticClass:"k-bar-slot",attrs:{"data-position":"right"}},[t._t("right")],2):t._e()])},Lu=[],qu=(n("6f7b"),{}),Au=Object(_["a"])(qu,Iu,Lu,!1,null,null,null),Nu=Au.exports,Bu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",t._g({staticClass:"k-box",attrs:{"data-theme":t.theme}},t.$listeners),[t._t("default",[n("k-text",{domProps:{innerHTML:t._s(t.text)}})])],2)},Pu=[],Du={props:{theme:String,text:String}},Ru=Du,Mu=(n("7dc7"),Object(_["a"])(Ru,Bu,Pu,!1,null,null,null)),zu=Mu.exports,Uu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("figure",t._g({staticClass:"k-card"},t.$listeners),[t.sortable?n("k-sort-handle"):t._e(),n(t.wrapper,{tag:"component",attrs:{to:t.link,target:t.target}},[t.imageOptions?n("k-image",t._b({staticClass:"k-card-image"},"k-image",t.imageOptions,!1)):n("span",{staticClass:"k-card-icon",style:"padding-bottom:"+t.ratioPadding},[n("k-icon",t._b({},"k-icon",t.icon,!1))],1),n("figcaption",{staticClass:"k-card-content"},[n("span",{staticClass:"k-card-text",attrs:{"data-noinfo":!t.info}},[t._v(t._s(t.text))]),t.info?n("span",{staticClass:"k-card-info",domProps:{innerHTML:t._s(t.info)}}):t._e()])],1),n("nav",{staticClass:"k-card-options"},[t.flag?n("k-button",t._b({staticClass:"k-card-options-button",on:{click:t.flag.click}},"k-button",t.flag,!1)):t._e(),t._t("options",[t.options?n("k-button",{staticClass:"k-card-options-button",attrs:{tooltip:t.$t("options"),icon:"dots"},on:{click:function(e){return e.stopPropagation(),t.$refs.dropdown.toggle()}}}):t._e(),n("k-dropdown-content",{ref:"dropdown",staticClass:"k-card-options-dropdown",attrs:{options:t.options,align:"right"},on:{action:function(e){return t.$emit("action",e)}}})])],2)],1)},Fu=[],Hu={inheritAttrs:!1,props:{column:String,flag:Object,icon:{type:Object,default:function(){return{type:"file",back:"black"}}},image:Object,info:String,link:String,options:[Array,Function],sortable:Boolean,target:String,text:String},computed:{wrapper:function(){return this.link?"k-link":"div"},ratioPadding:function(){return this.icon&&this.icon.ratio?this.$helper.ratio(this.icon.ratio):this.$helper.ratio("3/2")},imageOptions:function(){if(!this.image)return!1;var t=null,e=null;return this.image.cards?(t=this.image.cards.url,e=this.image.cards.srcset):(t=this.image.url,e=this.image.srcset),!!t&&{src:t,srcset:e,back:this.image.back||"black",cover:this.image.cover,ratio:this.image.ratio||"3/2",sizes:this.getSizes(this.column)}}},methods:{getSizes:function(t){switch(t){case"1/2":case"2/4":return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 44em, 27em";case"1/3":return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 29.333em, 27em";case"1/4":return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 22em, 27em";case"2/3":return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 27em, 27em";case"3/4":return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 66em, 27em";default:return"(min-width: 30em) and (max-width: 65em) 59em, (min-width: 65em) 88em, 27em"}}}},Ku=Hu,Vu=(n("c119"),Object(_["a"])(Ku,Uu,Fu,!1,null,null,null)),Yu=Vu.exports,Wu=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-cards"},[t._t("default",t._l(t.cards,function(e,i){return n("k-card",t._g(t._b({key:i},"k-card",e,!1),t.$listeners))}))],2)},Gu=[],Ju={props:{cards:Array}},Zu=Ju,Xu=(n("f56d"),Object(_["a"])(Zu,Wu,Gu,!1,null,null,null)),Qu=Xu.exports,tc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-collection",attrs:{"data-layout":t.layout}},[n("k-draggable",{attrs:{list:t.items,options:t.dragOptions,element:t.elements.list,"data-size":t.size,handle:!0},on:{change:function(e){return t.$emit("change",e)},end:t.onEnd}},t._l(t.items,function(e,i){return n(t.elements.item,t._b({key:i,tag:"component",class:{"k-draggable-item":e.sortable},on:{action:function(n){return t.$emit("action",e,n)},dragstart:function(n){return t.onDragStart(n,e.dragText)}}},"component",e,!1))}),1),t.hasFooter?n("footer",{staticClass:"k-collection-footer"},[t.help?n("k-text",{staticClass:"k-collection-help",attrs:{theme:"help"},domProps:{innerHTML:t._s(t.help)}}):t._e(),n("div",{staticClass:"k-collection-pagination"},[t.hasPagination?n("k-pagination",t._b({on:{paginate:function(e){return t.$emit("paginate",e)}}},"k-pagination",t.paginationOptions,!1)):t._e()],1)],1):t._e()],1)},ec=[],nc={props:{help:String,items:{type:[Array,Object],default:function(){return[]}},layout:{type:String,default:"list"},size:String,sortable:Boolean,pagination:{type:[Boolean,Object],default:function(){return!1}}},computed:{hasPagination:function(){return!1!==this.pagination&&(!0!==this.paginationOptions.hide&&!(this.pagination.total<=this.pagination.limit))},hasFooter:function(){return!(!this.hasPagination&&!this.help)},dragOptions:function(){return{sort:this.sortable,disabled:!1===this.sortable,draggable:".k-draggable-item"}},elements:function(){var t={cards:{list:"k-cards",item:"k-card"},list:{list:"k-list",item:"k-list-item"}};return t[this.layout]?t[this.layout]:t["list"]},paginationOptions:function(){var t="object"!==Object(Ht["a"])(this.pagination)?{}:this.pagination;return Object(I["a"])({limit:10,details:!0,keys:!1,total:0,hide:!1},t)}},watch:{$props:function(){this.$forceUpdate()}},over:null,methods:{onEnd:function(){this.over&&this.over.removeAttribute("data-over"),this.$emit("sort",this.items)},onDragStart:function(t,e){this.$store.dispatch("drag",{type:"text",data:e})}}},ic=nc,sc=(n("8c28"),Object(_["a"])(ic,tc,ec,!1,null,null,null)),ac=sc.exports,oc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-column",attrs:{"data-width":t.width}},[t._t("default")],2)},rc=[],lc={props:{width:String}},uc=lc,cc=(n("c9cb"),Object(_["a"])(uc,oc,rc,!1,null,null,null)),dc=cc.exports,pc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-dropzone",attrs:{"data-dragging":t.dragging,"data-over":t.over},on:{dragenter:t.onEnter,dragleave:t.onLeave,dragover:t.onOver,drop:t.onDrop}},[t._t("default")],2)},fc=[],hc={props:{label:{type:String,default:"Drop to upload"},disabled:{type:Boolean,default:!1}},data:function(){return{files:[],dragging:!1,over:!1}},methods:{cancel:function(){this.reset()},reset:function(){this.dragging=!1,this.over=!1},onDrop:function(t){return!0===this.disabled?this.reset():!1===this.$helper.isUploadEvent(t)?this.reset():(this.$events.$emit("dropzone.drop"),this.files=t.dataTransfer.files,this.$emit("drop",this.files),void this.reset())},onEnter:function(t){!1===this.disabled&&this.$helper.isUploadEvent(t)&&(this.dragging=!0)},onLeave:function(){this.reset()},onOver:function(t){!1===this.disabled&&this.$helper.isUploadEvent(t)&&(t.dataTransfer.dropEffect="copy",this.over=!0)}}},mc=hc,gc=(n("414d"),Object(_["a"])(mc,pc,fc,!1,null,null,null)),bc=gc.exports,vc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",t._g({staticClass:"k-empty",attrs:{"data-layout":t.layout}},t.$listeners),[t.icon?n("k-icon",{attrs:{type:t.icon}}):t._e(),n("p",[t._t("default")],2)],1)},kc=[],$c={props:{text:String,icon:String,layout:{type:String,default:"list"}}},_c=$c,yc=(n("ba8f"),Object(_["a"])(_c,vc,kc,!1,null,null,null)),xc=yc.exports,wc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-file-preview"},[n("k-view",{staticClass:"k-file-preview-layout"},[n("div",{staticClass:"k-file-preview-image"},[n("k-link",{staticClass:"k-file-preview-image-link",attrs:{to:t.file.url,title:t.$t("open"),target:"_blank"}},[t.file.panelImage&&t.file.panelImage.cards&&t.file.panelImage.cards.url?n("k-image",{attrs:{src:t.file.panelImage.cards.url,srcset:t.file.panelImage.cards.srcset,back:"none"}}):t.file.panelIcon?n("k-icon",{staticClass:"k-file-preview-icon",style:{color:t.file.panelIcon.color},attrs:{type:t.file.panelIcon.type}}):n("span",{staticClass:"k-file-preview-placeholder"})],1)],1),n("div",{staticClass:"k-file-preview-details"},[n("ul",[n("li",[n("h3",[t._v(t._s(t.$t("template")))]),n("p",[t._v(t._s(t.file.template||"—"))])]),n("li",[n("h3",[t._v(t._s(t.$t("mime")))]),n("p",[t._v(t._s(t.file.mime))])]),n("li",[n("h3",[t._v(t._s(t.$t("url")))]),n("p",[n("k-link",{attrs:{to:t.file.url,tabindex:"-1",target:"_blank"}},[t._v("/"+t._s(t.file.id))])],1)]),n("li",[n("h3",[t._v(t._s(t.$t("size")))]),n("p",[t._v(t._s(t.file.niceSize))])]),n("li",[n("h3",[t._v(t._s(t.$t("dimensions")))]),t.file.dimensions?n("p",[t._v(t._s(t.file.dimensions.width)+"×"+t._s(t.file.dimensions.height)+" "+t._s(t.$t("pixel")))]):n("p",[t._v("—")])]),n("li",[n("h3",[t._v(t._s(t.$t("orientation")))]),t.file.dimensions?n("p",[t._v(t._s(t.$t("orientation."+t.file.dimensions.orientation)))]):n("p",[t._v("—")])])])])])],1)},Oc=[],Cc={props:{file:Object}},Sc=Cc,Ec=(n("696b5"),Object(_["a"])(Sc,wc,Oc,!1,null,null,null)),jc=Ec.exports,Tc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-grid",attrs:{"data-gutter":t.gutter}},[t._t("default")],2)},Ic=[],Lc={props:{gutter:String}},qc=Lc,Ac=(n("5b23"),Object(_["a"])(qc,Tc,Ic,!1,null,null,null)),Nc=Ac.exports,Bc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("header",{staticClass:"k-header",attrs:{"data-editable":t.editable}},[n("k-headline",{attrs:{tag:"h1",size:"huge"}},[t.editable&&t.$listeners.edit?n("span",{staticClass:"k-headline-editable",on:{click:function(e){return t.$emit("edit")}}},[t._t("default"),n("k-icon",{attrs:{type:"edit"}})],2):t._t("default")],2),t.$slots.left||t.$slots.right?n("k-bar",{staticClass:"k-header-buttons"},[t._t("left",null,{slot:"left"}),t._t("right",null,{slot:"right"})],2):t._e(),t.tabs&&t.tabs.length>1?n("div",{staticClass:"k-header-tabs"},[n("nav",[t._l(t.visibleTabs,function(e,i){return n("k-button",{key:t.$route.fullPath+"-tab-"+i,staticClass:"k-tab-button",attrs:{link:"#"+e.name,current:t.currentTab&&t.currentTab.name===e.name,icon:e.icon,tooltip:e.label}},[t._v("\n "+t._s(e.label)+"\n ")])}),t.invisibleTabs.length?n("k-button",{staticClass:"k-tab-button k-tabs-dropdown-button",attrs:{icon:"dots"},on:{click:function(e){return e.stopPropagation(),t.$refs.more.toggle()}}},[t._v("\n "+t._s(t.$t("more"))+"\n ")]):t._e()],2),t.invisibleTabs.length?n("k-dropdown-content",{ref:"more",staticClass:"k-tabs-dropdown",attrs:{align:"right"}},t._l(t.invisibleTabs,function(e,i){return n("k-dropdown-item",{key:"more-"+i,attrs:{link:"#"+e.name,current:t.currentTab&&t.currentTab.name===e.name,icon:e.icon,tooltip:e.label}},[t._v("\n "+t._s(e.label)+"\n ")])}),1):t._e()],1):t._e()],1)},Pc=[],Dc={props:{editable:Boolean,tabs:Array,tab:Object},data:function(){return{size:null,currentTab:this.tab,visibleTabs:this.tabs,invisibleTabs:[]}},watch:{tab:function(){this.currentTab=this.tab},tabs:function(t){this.visibleTabs=t,this.invisibleTabs=[],this.resize(!0)}},created:function(){window.addEventListener("resize",this.resize)},destroyed:function(){window.removeEventListener("resize",this.resize)},methods:{resize:function(t){if(this.tabs&&!(this.tabs.length<=1)){if(this.tabs.length<=3)return this.visibleTabs=this.tabs,void(this.invisibleTabs=[]);if(window.innerWidth>=700){if("large"===this.size&&!t)return;this.visibleTabs=this.tabs,this.invisibleTabs=[],this.size="large"}else{if("small"===this.size&&!t)return;this.visibleTabs=this.tabs.slice(0,2),this.invisibleTabs=this.tabs.slice(2),this.size="small"}}}}},Rc=Dc,Mc=(n("53c5"),Object(_["a"])(Rc,Bc,Pc,!1,null,null,null)),zc=Mc.exports,Uc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ul",{staticClass:"k-list"},[t._t("default",t._l(t.items,function(e,i){return n("k-list-item",t._g(t._b({key:i},"k-list-item",e,!1),t.$listeners))}))],2)},Fc=[],Hc={props:{items:Array}},Kc=Hc,Vc=(n("c857"),Object(_["a"])(Kc,Uc,Fc,!1,null,null,null)),Yc=Vc.exports,Wc=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(t.element,t._g({tag:"component",staticClass:"k-list-item"},t.$listeners),[t.sortable?n("k-sort-handle"):t._e(),n("k-link",{staticClass:"k-list-item-content",attrs:{to:t.link,target:t.target}},[n("span",{staticClass:"k-list-item-image"},[t.imageOptions?n("k-image",t._b({},"k-image",t.imageOptions,!1)):n("k-icon",t._b({},"k-icon",t.icon,!1))],1),n("span",{staticClass:"k-list-item-text"},[n("em",[t._v(t._s(t.text))]),t.info?n("small",{domProps:{innerHTML:t._s(t.info)}}):t._e()])]),n("nav",{staticClass:"k-list-item-options"},[t._t("options",[t.flag?n("k-button",t._b({staticClass:"k-list-item-status",on:{click:t.flag.click}},"k-button",t.flag,!1)):t._e(),t.options?n("k-button",{staticClass:"k-list-item-toggle",attrs:{tooltip:t.$t("options"),icon:"dots",alt:"Options"},on:{click:function(e){return e.stopPropagation(),t.$refs.options.toggle()}}}):t._e(),n("k-dropdown-content",{ref:"options",attrs:{options:t.options,align:"right"},on:{action:function(e){return t.$emit("action",e)}}})])],2)],1)},Gc=[],Jc={inheritAttrs:!1,props:{element:{type:String,default:"li"},image:Object,icon:{type:Object,default:function(){return{type:"file",back:"black"}}},sortable:Boolean,text:String,target:String,info:String,link:String,flag:Object,options:[Array,Function]},computed:{imageOptions:function(){return Xl(this.image)}}},Zc=Jc,Xc=(n("fa6a"),Object(_["a"])(Zc,Wc,Gc,!1,null,null,null)),Qc=Xc.exports,td=function(){var t=this,e=t.$createElement,n=t._self._c||e;return 0===t.tabs.length?n("k-box",{attrs:{text:"This page has no blueprint setup yet",theme:"info"}}):t.tab?n("k-sections",{attrs:{parent:t.parent,blueprint:t.blueprint,columns:t.tab.columns},on:{submit:function(e){return t.$emit("submit",e)}}}):t._e()},ed=[],nd={props:{parent:String,blueprint:String,tabs:Array},data:function(){return{tab:null}},watch:{$route:function(){this.open()},blueprint:function(){this.open()}},mounted:function(){this.open()},methods:{open:function(t){if(0!==this.tabs.length){t||(t=this.$route.hash.replace("#","")),t||(t=this.tabs[0].name);var e=null;this.tabs.forEach(function(n){n.name===t&&(e=n)}),e||(e=this.tabs[0]),this.tab=e,this.$emit("tab",this.tab)}}}},id=nd,sd=Object(_["a"])(id,td,ed,!1,null,null,null),ad=sd.exports,od=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-view",attrs:{"data-align":t.align}},[t._t("default")],2)},rd=[],ld={props:{align:String}},ud=ld,cd=(n("daa8"),Object(_["a"])(ud,od,rd,!1,null,null,null)),dd=cd.exports,pd=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("draggable",t._g(t._b({staticClass:"k-draggable",attrs:{tag:t.element,list:t.list,move:t.move}},"draggable",t.dragOptions,!1),t.listeners),[t._t("default"),t._t("footer",null,{slot:"footer"})],2)},fd=[],hd=n("1980"),md=n.n(hd),gd={components:{draggable:md.a},props:{element:String,handle:[String,Boolean],list:[Array,Object],move:Function,options:Object},data:function(){var t=this;return{listeners:Object(I["a"])({},this.$listeners,{start:function(e){t.$store.dispatch("drag",{}),t.$listeners.start&&t.$listeners.start(e)},end:function(e){t.$store.dispatch("drag",null),t.$listeners.end&&t.$listeners.end(e)}})}},computed:{dragOptions:function(){var t=!1;return t=!0===this.handle?".k-sort-handle":this.handle,Object(I["a"])({fallbackClass:"k-sortable-fallback",fallbackOnBody:!0,forceFallback:!0,ghostClass:"k-sortable-ghost",handle:t,scroll:document.querySelector(".k-panel-view")},this.options)}}},bd=gd,vd=Object(_["a"])(bd,pd,fd,!1,null,null,null),kd=vd.exports,$d={data:function(){return{error:null}},errorCaptured:function(t){return A.debug&&window.console.warn(t),this.error=t,!1},render:function(t){return this.error?this.$slots.error?this.$slots.error[0]:this.$scopedSlots.error?this.$scopedSlots.error({error:this.error}):t("k-box",{attrs:{theme:"negative"}},this.error.message||this.error):this.$slots.default[0]}},_d=$d,yd=Object(_["a"])(_d,Ir,Lr,!1,null,null,null),xd=yd.exports,wd=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(t.tag,t._g({tag:"component",staticClass:"k-headline",attrs:{"data-theme":t.theme,"data-size":t.size}},t.$listeners),[t.link?n("k-link",{attrs:{to:t.link}},[t._t("default")],2):t._t("default")],2)},Od=[],Cd={props:{link:String,size:{type:String},tag:{type:String,default:"h2"},theme:{type:String}}},Sd=Cd,Ed=(n("f8a7"),Object(_["a"])(Sd,wd,Od,!1,null,null,null)),jd=Ed.exports,Td=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{class:"k-icon k-icon-"+t.type,attrs:{"aria-label":t.alt,role:t.alt?"img":null,"aria-hidden":!t.alt,"data-back":t.back,"data-size":t.size}},[t.emoji?n("span",{staticClass:"k-icon-emoji"},[t._v(t._s(t.type))]):n("svg",{style:{color:t.color},attrs:{viewBox:"0 0 16 16"}},[n("use",{attrs:{"xlink:href":"#icon-"+t.type}})])])},Id=[],Ld={props:{alt:String,color:String,back:String,emoji:Boolean,size:String,type:String}},qd=Ld,Ad=(n("3342"),Object(_["a"])(qd,Td,Id,!1,null,null,null)),Nd=Ad.exports,Bd=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",t._g({staticClass:"k-image",attrs:{"data-ratio":t.ratio,"data-back":t.back,"data-cover":t.cover}},t.$listeners),[n("span",{style:"padding-bottom:"+t.ratioPadding},[t.loaded?n("img",{key:t.src,attrs:{alt:t.alt||"",src:t.src,srcset:t.srcset,sizes:t.sizes},on:{dragstart:function(t){t.preventDefault()}}}):t._e(),t.loaded||t.error?t._e():n("k-loader",{attrs:{position:"center",theme:"light"}}),!t.loaded&&t.error?n("k-icon",{staticClass:"k-image-error",attrs:{type:"cancel"}}):t._e()],1)])},Pd=[],Dd={props:{alt:String,back:String,cover:Boolean,ratio:String,sizes:String,src:String,srcset:String},data:function(){return{loaded:{type:Boolean,default:!1},error:{type:Boolean,default:!1}}},computed:{ratioPadding:function(){return this.$helper.ratio(this.ratio||"1/1")}},created:function(){var t=this,e=new Image;e.onload=function(){t.loaded=!0,t.$emit("load")},e.onerror=function(){t.error=!0,t.$emit("error")},e.src=this.src}},Rd=Dd,Md=(n("0d56"),Object(_["a"])(Rd,Bd,Pd,!1,null,null,null)),zd=Md.exports,Ud=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("progress",{staticClass:"k-progress",attrs:{max:"100"},domProps:{value:t.state}},[t._v("\n "+t._s(t.state)+"%\n")])},Fd=[],Hd={props:{value:{type:Number,default:0}},data:function(){return{state:this.value}},methods:{set:function(t){this.state=t}}},Kd=Hd,Vd=(n("9799"),Object(_["a"])(Kd,Ud,Fd,!1,null,null,null)),Yd=Vd.exports,Wd=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{staticClass:"k-sort-handle",attrs:{"aria-hidden":"true"}},[n("svg",{attrs:{viewBox:"0 0 16 16"}},[n("use",{attrs:{"xlink:href":"#icon-sort"}})])])},Gd=[],Jd=(n("35cb"),{}),Zd=Object(_["a"])(Jd,Wd,Gd,!1,null,null,null),Xd=Zd.exports,Qd=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-text",attrs:{"data-align":t.align,"data-size":t.size,"data-theme":t.theme}},[t._t("default")],2)},tp=[],ep={props:{align:String,size:String,theme:String}},np=ep,ip=(n("b0d6"),Object(_["a"])(np,Qd,tp,!1,null,null,null)),sp=ip.exports,ap=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(t.component,t._g(t._b({ref:"button",tag:"component"},"component",t.$props,!1),t.$listeners),[t._t("default")],2)},op=[],rp={inheritAttrs:!1,props:{autofocus:Boolean,current:[String,Boolean],disabled:Boolean,icon:String,id:[String,Number],link:String,responsive:Boolean,rel:String,role:String,target:String,tabindex:String,theme:String,tooltip:String,type:{type:String,default:"button"}},computed:{component:function(){return!0===this.disabled?"k-button-disabled":this.link?"k-button-link":"k-button-native"}},methods:{focus:function(){this.$refs.button.focus&&this.$refs.button.focus()},tab:function(){this.$refs.button.tab&&this.$refs.button.tab()},untab:function(){this.$refs.button.untab&&this.$refs.button.untab()}}},lp=rp,up=(n("3787"),Object(_["a"])(lp,ap,op,!1,null,null,null)),cp=up.exports,dp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{staticClass:"k-button",attrs:{id:t.id,"data-disabled":!0,"data-responsive":t.responsive,"data-theme":t.theme,title:t.tooltip}},[t.icon?n("k-icon",{staticClass:"k-button-icon",attrs:{type:t.icon,alt:t.tooltip}}):t._e(),t.$slots.default?n("span",{staticClass:"k-button-text"},[t._t("default")],2):t._e()],1)},pp=[],fp={inheritAttrs:!1,props:{icon:String,id:[String,Number],responsive:Boolean,theme:String,tooltip:String}},hp=fp,mp=(n("16eb"),Object(_["a"])(hp,dp,pp,!1,null,null,null)),gp=mp.exports,bp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-button-group"},[t._t("default")],2)},vp=[],kp=(n("a567"),{}),$p=Object(_["a"])(kp,bp,vp,!1,null,null,null),_p=$p.exports,yp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-link",t._g({staticClass:"k-button",attrs:{"aria-current":t.current,autofocus:t.autofocus,id:t.id,"data-theme":t.theme,"data-responsive":t.responsive,rel:t.rel,role:t.role,tabindex:t.tabindex,target:t.target,title:t.tooltip,to:t.link}},t.$listeners),[t.icon?n("k-icon",{staticClass:"k-button-icon",attrs:{type:t.icon,alt:t.tooltip}}):t._e(),t.$slots.default?n("span",{staticClass:"k-button-text"},[t._t("default")],2):t._e()],1)},xp=[],wp={inheritAttrs:!1,props:{autofocus:Boolean,current:[String,Boolean],icon:String,id:[String,Number],link:String,rel:String,responsive:Boolean,role:String,target:String,tabindex:String,theme:String,tooltip:String}},Op=wp,Cp=Object(_["a"])(Op,yp,xp,!1,null,null,null),Sp=Cp.exports,Ep=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("button",t._g({staticClass:"k-button",attrs:{"aria-current":t.current,autofocus:t.autofocus,id:t.id,"data-theme":t.theme,"data-responsive":t.responsive,role:t.role,tabindex:t.tabindex,title:t.tooltip,type:t.type}},t.$listeners),[t.icon?n("k-icon",{staticClass:"k-button-icon",attrs:{type:t.icon,alt:t.tooltip}}):t._e(),t.$slots.default?n("span",{staticClass:"k-button-text"},[t._t("default")],2):t._e()],1)},jp=[],Tp={mounted:function(){this.$el.addEventListener("keyup",this.onTab,!0),this.$el.addEventListener("blur",this.onUntab,!0)},destroyed:function(){this.$el.removeEventListener("keyup",this.onTab,!0),this.$el.removeEventListener("blur",this.onUntab,!0)},methods:{focus:function(){this.$el.focus&&this.$el.focus()},onTab:function(t){9===t.keyCode&&this.$el.setAttribute("data-tabbed",!0)},onUntab:function(){this.$el.removeAttribute("data-tabbed")},tab:function(){this.$el.focus(),this.$el.setAttribute("data-tabbed",!0)},untab:function(){this.$el.removeAttribute("data-tabbed")}}},Ip={mixins:[Tp],inheritAttrs:!1,props:{autofocus:Boolean,current:[String,Boolean],icon:String,id:[String,Number],responsive:Boolean,role:String,tabindex:String,theme:String,tooltip:String,type:{type:String,default:"button"}}},Lp=Ip,qp=Object(_["a"])(Lp,Ep,jp,!1,null,null,null),Ap=qp.exports,Np=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{staticClass:"k-dropdown",on:{click:function(t){t.stopPropagation()}}},[t._t("default")],2)},Bp=[],Pp=(n("f95f"),{}),Dp=Object(_["a"])(Pp,Np,Bp,!1,null,null,null),Rp=Dp.exports,Mp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.isOpen?n("div",{staticClass:"k-dropdown-content",attrs:{"data-align":t.align}},[t._t("default",[t._l(t.items,function(e,i){return["-"===e?n("hr",{key:t._uid+"-item-"+i}):n("k-dropdown-item",t._b({key:t._uid+"-item-"+i,ref:t._uid+"-item-"+i,refInFor:!0,on:{click:function(n){return t.$emit("action",e.click)}}},"k-dropdown-item",e,!1),[t._v("\n "+t._s(e.text)+"\n ")])]})])],2):t._e()},zp=[],Up=null,Fp={props:{options:[Array,Function],align:String},data:function(){return{items:[],current:-1,isOpen:!1}},methods:{fetchOptions:function(t){if(!this.options)return t(this.items);"string"===typeof this.options?fetch(this.options).then(function(t){return t.json()}).then(function(e){return t(e)}):"function"===typeof this.options?this.options(t):xt()(this.options)&&t(this.options)},open:function(){var t=this;this.reset(),Up&&Up!==this&&Up.close(),this.fetchOptions(function(e){t.$events.$on("keydown",t.navigate),t.$events.$on("click",t.close),t.items=e,t.isOpen=!0,t.$emit("open"),Up=t})},reset:function(){this.current=-1,this.$events.$off("keydown",this.navigate),this.$events.$off("click",this.close)},close:function(){this.reset(),this.isOpen=Up=!1,this.$emit("close")},toggle:function(){this.isOpen?this.close():this.open()},focus:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;this.$children[t]&&this.$children[t].focus&&(this.current=t,this.$children[t].focus())},navigate:function(t){switch(t.code){case"Escape":case"ArrowLeft":this.close(),this.$emit("leave",t.code);break;case"ArrowUp":t.preventDefault();while(1){if(this.current--,this.current<0){this.close(),this.$emit("leave",t.code);break}if(this.$children[this.current]&&!1===this.$children[this.current].disabled){this.focus(this.current);break}}break;case"ArrowDown":t.preventDefault();while(1){if(this.current++,this.current>this.$children.length-1){var e=this.$children.filter(function(t){return!1===t.disabled});this.current=this.$children.indexOf(e[e.length-1]);break}if(this.$children[this.current]&&!1===this.$children[this.current].disabled){this.focus(this.current);break}}break;case"Tab":while(1){if(this.current++,this.current>this.$children.length-1){this.close(),this.$emit("leave",t.code);break}if(this.$children[this.current]&&!1===this.$children[this.current].disabled)break}break}}}},Hp=Fp,Kp=(n("98a1"),Object(_["a"])(Hp,Mp,zp,!1,null,null,null)),Vp=Kp.exports,Yp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-button",t._g(t._b({ref:"button",staticClass:"k-dropdown-item"},"k-button",t.$props,!1),t.listeners),[t._t("default")],2)},Wp=[],Gp={inheritAttrs:!1,props:{disabled:Boolean,icon:String,image:[String,Object],link:String,target:String,theme:String,upload:String,current:[String,Boolean]},data:function(){var t=this;return{listeners:Object(I["a"])({},this.$listeners,{click:function(e){t.$parent.close(),t.$emit("click",e)}})}},methods:{focus:function(){this.$refs.button.focus()},tab:function(){this.$refs.button.tab()}}},Jp=Gp,Zp=(n("580a"),Object(_["a"])(Jp,Yp,Wp,!1,null,null,null)),Xp=Zp.exports,Qp=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.to&&!t.disabled?n("a",t._g({ref:"link",staticClass:"k-link",attrs:{href:t.href,rel:t.relAttr,tabindex:t.tabindex,target:t.target,title:t.title}},t.listeners),[t._t("default")],2):n("span",{staticClass:"k-link",attrs:{title:t.title,"data-disabled":""}},[t._t("default")],2)},tf=[],ef={mixins:[Tp],props:{disabled:Boolean,rel:String,tabindex:[String,Number],target:String,title:String,to:String},data:function(){return{relAttr:"_blank"===this.target?"noreferrer noopener":this.rel,listeners:Object(I["a"])({},this.$listeners,{click:this.onClick})}},computed:{href:function(){return void 0===this.$route||"/"!==this.to[0]||this.target?this.to:(this.$router.options.url||"")+this.to}},methods:{isRoutable:function(t){return void 0!==this.$route&&(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)&&(!t.defaultPrevented&&((void 0===t.button||0===t.button)&&!this.target)))},onClick:function(t){if(!0===this.disabled)return t.preventDefault(),!1;this.isRoutable(t)&&(t.preventDefault(),this.$router.push(this.to)),this.$emit("click",t)}}},nf=ef,sf=(n("cc79"),Object(_["a"])(nf,Qp,tf,!1,null,null,null)),af=sf.exports,of=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.languages.length?n("k-dropdown",[n("k-button",{attrs:{responsive:!0,icon:"globe"},on:{click:function(e){return t.$refs.languages.toggle()}}},[t._v("\n "+t._s(t.language.name)+"\n ")]),t.languages?n("k-dropdown-content",{ref:"languages"},[n("k-dropdown-item",{on:{click:function(e){return t.change(t.defaultLanguage)}}},[t._v(t._s(t.defaultLanguage.name))]),n("hr"),t._l(t.languages,function(e){return n("k-dropdown-item",{key:e.code,on:{click:function(n){return t.change(e)}}},[t._v("\n "+t._s(e.name)+"\n ")])})],2):t._e()],1):t._e()},rf=[],lf={computed:{defaultLanguage:function(){return this.$store.state.languages.default},language:function(){return this.$store.state.languages.current},languages:function(){return this.$store.state.languages.all.filter(function(t){return!1===t.default})}},methods:{change:function(t){this.$store.dispatch("languages/current",t),this.$emit("change",t)}}},uf=lf,cf=Object(_["a"])(uf,of,rf,!1,null,null,null),df=cf.exports,pf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.show?n("nav",{staticClass:"k-pagination",attrs:{"data-align":t.align}},[t.show?n("k-button",{attrs:{disabled:!t.hasPrev,tooltip:t.prevLabel,icon:"angle-left"},on:{click:t.prev}}):t._e(),t.details?[t.dropdown?[n("k-dropdown",[n("k-button",{staticClass:"k-pagination-details",attrs:{disabled:!t.hasPages},on:{click:function(e){return t.$refs.dropdown.toggle()}}},[t.total>1?[t._v(t._s(t.detailsText))]:t._e(),t._v(t._s(t.total)+"\n ")],2),n("k-dropdown-content",{ref:"dropdown",staticClass:"k-pagination-selector",on:{open:function(e){t.$nextTick(function(){return t.$refs.page.focus()})}}},[n("div",{staticClass:"k-pagination-settings"},[n("label",{attrs:{for:"k-pagination-page"}},[n("span",[t._v(t._s(t.pageLabel)+":")]),n("select",{ref:"page",attrs:{id:"k-pagination-page"}},t._l(t.pages,function(e){return n("option",{key:e,domProps:{selected:t.page===e,value:e}},[t._v("\n "+t._s(e)+"\n ")])}),0)]),n("k-button",{attrs:{icon:"check"},on:{click:function(e){return t.goTo(t.$refs.page.value)}}})],1)])],1)]:[n("span",{staticClass:"k-pagination-details"},[t.total>1?[t._v(t._s(t.detailsText))]:t._e(),t._v(t._s(t.total)+"\n ")],2)]]:t._e(),t.show?n("k-button",{attrs:{disabled:!t.hasNext,tooltip:t.nextLabel,icon:"angle-right"},on:{click:t.next}}):t._e()],2):t._e()},ff=[],hf={props:{align:{type:String,default:"left"},details:{type:Boolean,default:!1},dropdown:{type:Boolean,default:!0},validate:{type:Function,default:function(){return Je.a.resolve()}},page:{type:Number,default:1},total:{type:Number,default:0},limit:{type:Number,default:10},keys:{type:Boolean,default:!1},pageLabel:{type:String,default:function(){return this.$t("pagination.page")}},prevLabel:{type:String,default:function(){return this.$t("prev")}},nextLabel:{type:String,default:function(){return this.$t("next")}}},data:function(){return{currentPage:this.page}},computed:{show:function(){return this.pages>1},start:function(){return(this.currentPage-1)*this.limit+1},end:function(){var t=this.start-1+this.limit;return t>this.total?this.total:t},detailsText:function(){return 1===this.limit?this.start+" / ":this.start+"-"+this.end+" / "},pages:function(){return Math.ceil(this.total/this.limit)},hasPrev:function(){return this.start>1},hasNext:function(){return this.endthis.limit},offset:function(){return this.start-1}},watch:{page:function(t){this.currentPage=ms()(t)}},created:function(){!0===this.keys&&window.addEventListener("keydown",this.navigate,!1)},destroyed:function(){window.removeEventListener("keydown",this.navigate,!1)},methods:{goTo:function(t){var e=this;this.validate(t).then(function(){t<1&&(t=1),t>e.pages&&(t=e.pages),e.currentPage=t,e.$refs.dropdown&&e.$refs.dropdown.close(),e.$emit("paginate",{page:e.currentPage,start:e.start,end:e.end,limit:e.limit,offset:e.offset})}).catch(function(){})},prev:function(){this.goTo(this.currentPage-1)},next:function(){this.goTo(this.currentPage+1)},navigate:function(t){switch(t.code){case"ArrowLeft":this.prev();break;case"ArrowRight":this.next();break}}}},mf=hf,gf=(n("a66d"),Object(_["a"])(mf,pf,ff,!1,null,null,null)),bf=gf.exports,vf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-button-group",{staticClass:"k-prev-next"},[n("k-button",t._b({attrs:{icon:"angle-left"}},"k-button",t.prev,!1)),n("k-button",t._b({attrs:{icon:"angle-right"}},"k-button",t.next,!1))],1)},kf=[],$f={props:{prev:{type:Object,default:function(){return{disabled:!0,link:"#"}}},next:{type:Object,default:function(){return{disabled:!0,link:"#"}}}}},_f=$f,yf=(n("7a7d"),Object(_["a"])(_f,vf,kf,!1,null,null,null)),xf=yf.exports,wf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"k-search",attrs:{role:"search"},on:{click:t.close}},[n("div",{staticClass:"k-search-box",on:{click:function(t){t.stopPropagation()}}},[n("div",{staticClass:"k-search-input"},[n("k-dropdown",{staticClass:"k-search-types"},[n("k-button",{attrs:{icon:t.type.icon},on:{click:function(e){return t.$refs.types.toggle()}}},[t._v(t._s(t.type.label)+":")]),n("k-dropdown-content",{ref:"types"},t._l(t.types,function(e,i){return n("k-dropdown-item",{key:i,attrs:{icon:e.icon},on:{click:function(e){t.currentType=i}}},[t._v("\n "+t._s(e.label)+"\n ")])}),1)],1),n("input",{directives:[{name:"model",rawName:"v-model",value:t.q,expression:"q"}],ref:"input",attrs:{placeholder:t.$t("search")+" …","aria-label":"$t('search')",type:"text"},domProps:{value:t.q},on:{keydown:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"down",40,e.key,["Down","ArrowDown"])?null:(e.preventDefault(),t.down(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"up",38,e.key,["Up","ArrowUp"])?null:(e.preventDefault(),t.up(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"tab",9,e.key,"Tab")?null:(e.preventDefault(),t.tab(e))},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:t.enter(e)},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"esc",27,e.key,["Esc","Escape"])?null:t.close(e)}],input:function(e){e.target.composing||(t.q=e.target.value)}}}),n("k-button",{staticClass:"k-search-close",attrs:{tooltip:t.$t("close"),icon:"cancel"},on:{click:t.close}})],1),n("ul",t._l(t.items,function(e,i){return n("li",{key:e.id,attrs:{"data-selected":t.selected===i},on:{mouseover:function(e){t.selected=i}}},[n("k-link",{attrs:{to:e.link},on:{click:function(e){return t.click(i)}}},[n("strong",[t._v(t._s(e.title))]),n("small",[t._v(t._s(e.info))])])],1)}),0)])])},Of=[],Cf={data:function(){return{items:[],q:null,selected:-1,currentType:"users"===this.$store.state.view?"users":"pages"}},computed:{type:function(){return this.types[this.currentType]||this.types["pages"]},types:function(){return{pages:{label:this.$t("pages"),icon:"page",endpoint:"site/search"},users:{label:this.$t("users"),icon:"users",endpoint:"users/search"}}}},watch:{q:wt(function(t){this.search(t)},200),currentType:function(){this.search(this.q)}},mounted:function(){var t=this;this.$nextTick(function(){t.$refs.input.focus()})},methods:{open:function(t){t.preventDefault(),this.$store.dispatch("search",!0)},click:function(t){this.selected=t,this.tab()},close:function(){this.$store.dispatch("search",!1)},down:function(){this.selected=0&&this.selected--}}},Sf=Cf,Ef=(n("4cb2"),Object(_["a"])(Sf,wf,Of,!1,null,null,null)),jf=Ef.exports,Tf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("span",{ref:"button",staticClass:"k-tag",attrs:{"data-size":t.size,tabindex:"0"},on:{keydown:function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"delete",[8,46],e.key,["Backspace","Delete","Del"])?null:(e.preventDefault(),t.remove(e))}}},[n("span",{staticClass:"k-tag-text"},[t._t("default")],2),t.removable?n("span",{staticClass:"k-tag-toggle",on:{click:t.remove}},[t._v("×")]):t._e()])},If=[],Lf={props:{removable:Boolean,size:String},methods:{remove:function(){this.removable&&this.$emit("remove")},focus:function(){this.$refs.button.focus()}}},qf=Lf,Af=(n("021f"),Object(_["a"])(qf,Tf,If,!1,null,null,null)),Nf=Af.exports,Bf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.user&&t.view?n("div",{staticClass:"k-topbar"},[n("k-view",[n("div",{staticClass:"k-topbar-wrapper"},[n("k-dropdown",{staticClass:"k-topbar-menu"},[n("k-button",{staticClass:"k-topbar-button k-topbar-menu-button",attrs:{tooltip:t.$t("menu"),icon:"bars"},on:{click:function(e){return t.$refs.menu.toggle()}}},[n("k-icon",{attrs:{type:"angle-down"}})],1),n("k-dropdown-content",{ref:"menu",staticClass:"k-topbar-menu"},[n("ul",[t._l(t.views,function(e,i){return e.menu?n("li",{key:"menu-item-"+i,attrs:{"aria-current":t.$store.state.view===i}},[n("k-dropdown-item",{attrs:{disabled:!1===t.$permissions.access[i],icon:e.icon,link:e.link}},[t._v("\n "+t._s(t.menuTitle(e,i))+"\n ")])],1):t._e()}),n("li",[n("hr")]),n("li",{attrs:{"aria-current":"account"===t.$route.meta.view}},[n("k-dropdown-item",{attrs:{icon:"account",link:"/account"}},[t._v("\n "+t._s(t.$t("view.account"))+"\n ")])],1),n("li",[n("hr")]),n("li",[n("k-dropdown-item",{attrs:{icon:"logout",link:"/logout"}},[t._v("\n "+t._s(t.$t("logout"))+"\n ")])],1)],2)])],1),t.view?n("k-link",{staticClass:"k-topbar-button k-topbar-view-button",attrs:{to:t.view.link}},[n("k-icon",{attrs:{type:t.view.icon}}),t._v(" "+t._s(t.breadcrumbTitle)+"\n ")],1):t._e(),t.$store.state.breadcrumb.length>1?n("k-dropdown",{staticClass:"k-topbar-breadcrumb-menu"},[n("k-button",{staticClass:"k-topbar-button",on:{click:function(e){return t.$refs.crumb.toggle()}}},[t._v("\n …\n "),n("k-icon",{attrs:{type:"angle-down"}})],1),n("k-dropdown-content",{ref:"crumb"},[n("k-dropdown-item",{attrs:{icon:t.view.icon,link:t.view.link}},[t._v("\n "+t._s(t.$t("view."+t.$store.state.view,t.view.label))+"\n ")]),t._l(t.$store.state.breadcrumb,function(e,i){return n("k-dropdown-item",{key:"crumb-"+i+"-dropdown",attrs:{icon:t.view.icon,link:e.link}},[t._v("\n "+t._s(e.label)+"\n ")])})],2)],1):t._e(),n("nav",{staticClass:"k-topbar-crumbs"},t._l(t.$store.state.breadcrumb,function(e,i){return n("k-link",{key:"crumb-"+i,attrs:{to:e.link}},[t._v("\n "+t._s(e.label)+"\n ")])}),1),n("div",{staticClass:"k-topbar-signals"},[n("span",{directives:[{name:"show",rawName:"v-show",value:t.$store.state.isLoading,expression:"$store.state.isLoading"}],staticClass:"k-topbar-loader"},[n("svg",{attrs:{viewBox:"0 0 16 18"}},[n("path",{attrs:{fill:"white",d:"M8,0 L16,4.50265232 L16,13.5112142 L8,18.0138665 L0,13.5112142 L0,4.50265232 L8,0 Z M2.10648757,5.69852516 L2.10648757,12.3153414 L8,15.632396 L13.8935124,12.3153414 L13.8935124,5.69852516 L8,2.38147048 L2.10648757,5.69852516 Z"}})])]),t.notification?[n("k-button",{staticClass:"k-topbar-notification k-topbar-signals-button",attrs:{theme:"positive"},on:{click:function(e){return t.$store.dispatch("notification/close")}}},[t._v("\n "+t._s(t.notification.message)+"\n ")])]:t.unregistered?[n("div",{staticClass:"k-registration"},[n("p",[t._v(t._s(t.$t("license.unregistered")))]),n("k-button",{staticClass:"k-topbar-signals-button",attrs:{responsive:!0,tooltip:t.$t("license.unregistered"),icon:"key"},on:{click:function(e){return t.$emit("register")}}},[t._v("\n "+t._s(t.$t("license.register"))+"\n ")]),n("k-button",{staticClass:"k-topbar-signals-button",attrs:{responsive:!0,link:"https://getkirby.com/buy",target:"_blank",icon:"cart"}},[t._v("\n "+t._s(t.$t("license.buy"))+"\n ")])],1)]:t._e(),[n("k-form-indicator")],n("k-button",{staticClass:"k-topbar-signals-button",attrs:{tooltip:t.$t("search"),icon:"search"},on:{click:function(e){return t.$store.dispatch("search",!0)}}})],2)],1)])],1):t._e()},Pf=[],Df=Object(I["a"])({site:{link:"/site",icon:"page",menu:!0},users:{link:"/users",icon:"users",menu:!0},settings:{link:"/settings",icon:"settings",menu:!0},account:{link:"/account",icon:"users",menu:!1}},window.panel.plugins.views),Rf={computed:{breadcrumbTitle:function(){var t=this.$t("view.".concat(this.$store.state.view),this.view.label);return"site"===this.$store.state.view&&this.$store.state.system.info.title||t},view:function(){return Df[this.$store.state.view]},views:function(){return Df},user:function(){return this.$store.state.user.current},notification:function(){return this.$store.state.notification.type&&"error"!==this.$store.state.notification.type?this.$store.state.notification:null},unregistered:function(){return!this.$store.state.system.info.license}},methods:{menuTitle:function(t,e){var n=this.$t("view."+e,t.label);return"site"===e&&this.$store.state.system.info.site||n}}},Mf=Rf,zf=(n("1e3b"),Object(_["a"])(Mf,Bf,Pf,!1,null,null,null)),Uf=zf.exports,Ff=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-grid",{staticClass:"k-sections",attrs:{gutter:"large"}},t._l(t.columns,function(e,i){return n("k-column",{key:t.parent+"-column-"+i,attrs:{width:e.width}},[t._l(e.sections,function(s,a){return t.meetsCondition(s)?[t.exists(s.type)?n("k-"+s.type+"-section",t._b({key:t.parent+"-column-"+i+"-section-"+a+"-"+t.blueprint,tag:"component",class:"k-section k-section-name-"+s.name,attrs:{name:s.name,parent:t.parent,blueprint:t.blueprint,column:e.width},on:{submit:function(e){return t.$emit("submit",e)}}},"component",s,!1)):[n("k-box",{key:t.parent+"-column-"+i+"-section-"+a,attrs:{text:t.$t("error.section.type.invalid",{type:s.type}),theme:"negative"}})]]:t._e()})],2)}),1)},Hf=[],Kf={props:{parent:String,blueprint:String,columns:[Array,Object]},computed:{content:function(){return this.$store.getters["content/values"]()}},methods:{exists:function(t){return z["a"].options.components["k-"+t+"-section"]},meetsCondition:function(t){var e=this;if(!t.when)return!0;var n=!0;return kt()(t.when).forEach(function(i){var s=e.content[i.toLowerCase()],a=t.when[i];s!==a&&(n=!1)}),n}}},Vf=Kf,Yf=(n("6bcd"),Object(_["a"])(Vf,Ff,Hf,!1,null,null,null)),Wf=Yf.exports,Gf=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{staticClass:"k-info-section"},[n("k-headline",{staticClass:"k-info-section-headline"},[t._v(t._s(t.headline))]),n("k-box",{attrs:{theme:t.theme}},[n("k-text",{domProps:{innerHTML:t._s(t.text)}})],1)],1)},Jf=[],Zf={props:{blueprint:String,help:String,name:String,parent:String},methods:{load:function(){return this.$api.get(this.parent+"/sections/"+this.name)}}},Xf={mixins:[Zf],data:function(){return{headline:null,issue:null,text:null,theme:null}},created:function(){var t=this;this.load().then(function(e){t.headline=e.options.headline,t.text=e.options.text,t.theme=e.options.theme||"info"}).catch(function(e){t.issue=e})}},Qf=Xf,th=(n("4333"),Object(_["a"])(Qf,Gf,Jf,!1,null,null,null)),eh=th.exports,nh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return!1===t.isLoading?n("section",{staticClass:"k-pages-section"},[n("header",{staticClass:"k-section-header"},[n("k-headline",{attrs:{link:t.options.link}},[t._v("\n "+t._s(t.headline)+" "),t.options.min?n("abbr",{attrs:{title:t.$t("section.required")}},[t._v("*")]):t._e()]),t.add?n("k-button-group",[n("k-button",{attrs:{icon:"add"},on:{click:t.create}},[t._v(t._s(t.$t("add")))])],1):t._e()],1),t.error?[n("k-box",{attrs:{theme:"negative"}},[n("k-text",{attrs:{size:"small"}},[n("strong",[t._v("\n "+t._s(t.$t("error.section.notLoaded",{name:t.name}))+":\n ")]),t._v("\n "+t._s(t.error)+"\n ")])],1)]:[t.data.length?n("k-collection",{attrs:{layout:t.options.layout,help:t.help,items:t.data,pagination:t.pagination,sortable:t.options.sortable,size:t.options.size,"data-invalid":t.isInvalid},on:{change:t.sort,paginate:t.paginate,action:t.action}}):[n("k-empty",{attrs:{layout:t.options.layout,"data-invalid":t.isInvalid,icon:"page"},on:{click:t.create}},[t._v("\n "+t._s(t.options.empty||t.$t("pages.empty"))+"\n ")]),n("footer",{staticClass:"k-collection-footer"},[t.help?n("k-text",{staticClass:"k-collection-help",attrs:{theme:"help"},domProps:{innerHTML:t._s(t.help)}}):t._e()],1)],n("k-page-create-dialog",{ref:"create"}),n("k-page-duplicate-dialog",{ref:"duplicate"}),n("k-page-rename-dialog",{ref:"rename",on:{success:t.update}}),n("k-page-url-dialog",{ref:"url",on:{success:t.update}}),n("k-page-status-dialog",{ref:"status",on:{success:t.update}}),n("k-page-template-dialog",{ref:"template",on:{success:t.update}}),n("k-page-remove-dialog",{ref:"remove",on:{success:t.update}})]],2):t._e()},ih=[],sh={inheritAttrs:!1,props:{blueprint:String,column:String,parent:String,name:String},data:function(){return{data:[],error:null,isLoading:!1,options:{empty:null,headline:null,help:null,layout:"list",link:null,max:null,min:null,size:null,sortable:null},pagination:{page:null}}},computed:{headline:function(){return this.options.headline||" "},help:function(){return this.options.help},isInvalid:function(){return!!(this.options.min&&this.data.lengththis.options.max)},language:function(){return this.$store.state.languages.current},paginationId:function(){return"kirby$pagination$"+this.parent+"/"+this.name}},watch:{language:function(){this.reload()}},methods:{items:function(t){return t},load:function(t){var e=this;t||(this.isLoading=!0),null===this.pagination.page&&(this.pagination.page=localStorage.getItem(this.paginationId)||1),this.$api.get(this.parent+"/sections/"+this.name,{page:this.pagination.page}).then(function(t){e.isLoading=!1,e.options=t.options,e.pagination=t.pagination,e.data=e.items(t.data)}).catch(function(t){e.isLoading=!1,e.error=t.message})},paginate:function(t){localStorage.setItem(this.paginationId,t.page),this.pagination=t,this.reload()},reload:function(){this.load(!0)}}},ah={mixins:[sh],computed:{add:function(){return this.options.add&&this.$permissions.pages.create}},created:function(){this.load(),this.$events.$on("page.changeStatus",this.reload)},destroyed:function(){this.$events.$off("page.changeStatus",this.reload)},methods:{create:function(){this.add&&this.$refs.create.open(this.options.link||this.parent,this.parent+"/children/blueprints",this.name)},action:function(t,e){var n=this;switch(e){case"duplicate":this.$refs.duplicate.open(t.id);break;case"preview":var i=window.open("","_blank");i.document.write="...",this.$api.pages.preview(t.id).then(function(t){i.location.href=t}).catch(function(t){n.$store.dispatch("notification/error",t)});break;case"rename":this.$refs.rename.open(t.id);break;case"url":this.$refs.url.open(t.id);break;case"status":this.$refs.status.open(t.id);break;case"template":this.$refs.template.open(t.id);break;case"remove":if(this.data.length<=this.options.min){var s=this.options.min>1?"plural":"singular";this.$store.dispatch("notification/error",{message:this.$t("error.section.pages.min."+s,{section:this.options.headline||this.name,min:this.options.min})});break}this.$refs.remove.open(t.id);break;default:throw new Error("Invalid action")}},items:function(t){var e=this;return t.map(function(t){var n=!1!==t.permissions.changeStatus;return t.flag={class:"k-status-flag k-status-flag-"+t.status,tooltip:n?e.$t("page.status"):"".concat(e.$t("page.status")," (").concat(e.$t("disabled"),")"),icon:n?"circle":"protected",disabled:!n,click:function(){e.action(t,"status")}},t.options=function(n){e.$api.pages.options(t.id,"list").then(function(t){return n(t)}).catch(function(t){e.$store.dispatch("notification/error",t)})},t.sortable=t.permissions.sort&&e.options.sortable,t.column=e.column,t})},sort:function(t){var e=this,n=null;if(t.added&&(n="added"),t.moved&&(n="moved"),n){var i=t[n].element,s=t[n].newIndex+1+this.pagination.offset;this.$api.pages.status(i.id,"listed",s).then(function(){e.$store.dispatch("notification/success",":)")}).catch(function(t){e.$store.dispatch("notification/error",{message:t.message,details:t.details}),e.reload()})}},update:function(){this.reload(),this.$events.$emit("model.update")}}},oh=ah,rh=Object(_["a"])(oh,nh,ih,!1,null,null,null),lh=rh.exports,uh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return!1===t.isLoading?n("section",{staticClass:"k-files-section"},[n("header",{staticClass:"k-section-header"},[n("k-headline",[t._v("\n "+t._s(t.headline)+" "),t.options.min?n("abbr",{attrs:{title:t.$t("section.required")}},[t._v("*")]):t._e()]),t.add?n("k-button-group",[n("k-button",{attrs:{icon:"upload"},on:{click:t.upload}},[t._v(t._s(t.$t("add")))])],1):t._e()],1),t.error?[n("k-box",{attrs:{theme:"negative"}},[n("k-text",{attrs:{size:"small"}},[n("strong",[t._v(t._s(t.$t("error.section.notLoaded",{name:t.name}))+":")]),t._v("\n "+t._s(t.error)+"\n ")])],1)]:[n("k-dropzone",{attrs:{disabled:!1===t.add},on:{drop:t.drop}},[t.data.length?n("k-collection",{attrs:{help:t.help,items:t.data,layout:t.options.layout,pagination:t.pagination,sortable:t.options.sortable,size:t.options.size,"data-invalid":t.isInvalid},on:{sort:t.sort,paginate:t.paginate,action:t.action}}):[n("k-empty",{attrs:{layout:t.options.layout,"data-invalid":t.isInvalid,icon:"image"},on:{click:function(e){t.add&&t.upload()}}},[t._v("\n "+t._s(t.options.empty||t.$t("files.empty"))+"\n ")]),n("footer",{staticClass:"k-collection-footer"},[t.help?n("k-text",{staticClass:"k-collection-help",attrs:{theme:"help"},domProps:{innerHTML:t._s(t.help)}}):t._e()],1)]],2),n("k-file-rename-dialog",{ref:"rename",on:{success:t.update}}),n("k-file-remove-dialog",{ref:"remove",on:{success:t.update}}),n("k-upload",{ref:"upload",on:{success:t.uploaded,error:t.reload}})]],2):t._e()},ch=[],dh={mixins:[sh],computed:{add:function(){return!(!this.$permissions.files.create||!1===this.options.upload)&&this.options.upload}},created:function(){this.load(),this.$events.$on("model.update",this.reload)},destroyed:function(){this.$events.$off("model.update",this.reload)},methods:{action:function(t,e){switch(e){case"edit":this.$router.push(t.link);break;case"download":window.open(t.url);break;case"rename":this.$refs.rename.open(t.parent,t.filename);break;case"replace":this.$refs.upload.open({url:A.api+"/"+this.$api.files.url(t.parent,t.filename),accept:t.mime,multiple:!1});break;case"remove":if(this.data.length<=this.options.min){var n=this.options.min>1?"plural":"singular";this.$store.dispatch("notification/error",{message:this.$t("error.section.files.min."+n,{section:this.options.headline||this.name,min:this.options.min})});break}this.$refs.remove.open(t.parent,t.filename);break}},drop:function(t){if(!1===this.add)return!1;this.$refs.upload.drop(t,Object(I["a"])({},this.add,{url:A.api+"/"+this.add.api}))},items:function(t){var e=this;return t.map(function(t){return t.options=function(n){e.$api.files.options(t.parent,t.filename,"list").then(function(t){return n(t)}).catch(function(t){e.$store.dispatch("notification/error",t)})},t.sortable=e.options.sortable,t.column=e.column,t})},replace:function(t){this.$refs.upload.open({url:A.api+"/"+this.$api.files.url(t.parent,t.filename),accept:t.mime,multiple:!1})},sort:function(t){var e=this;if(!1===this.options.sortable)return!1;t=t.map(function(t){return t.id}),this.$api.patch(this.parent+"/files/sort",{files:t,index:this.pagination.offset}).then(function(){e.$store.dispatch("notification/success",":)")}).catch(function(t){e.reload(),e.$store.dispatch("notification/error",t.message)})},update:function(){this.$events.$emit("model.update")},upload:function(){if(!1===this.add)return!1;this.$refs.upload.open(Object(I["a"])({},this.add,{url:A.api+"/"+this.add.api}))},uploaded:function(){this.$events.$emit("file.create"),this.$events.$emit("model.update"),this.$store.dispatch("notification/success",":)")}}},ph=dh,fh=Object(_["a"])(ph,uh,ch,!1,null,null,null),hh=fh.exports,mh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.isLoading?t._e():n("section",{staticClass:"k-fields-section"},[t.issue?[n("k-headline",{staticClass:"k-fields-issue-headline"},[t._v("Error")]),n("k-box",{attrs:{text:t.issue.message,theme:"negative"}})]:t._e(),n("k-form",{attrs:{fields:t.fields,validate:!0,value:t.values,disabled:null!==t.$store.state.content.status.lock},on:{input:t.input,submit:t.onSubmit}})],2)},gh=[],bh={mixins:[Zf],inheritAttrs:!1,data:function(){return{fields:{},isLoading:!0,issue:null}},computed:{language:function(){return this.$store.state.languages.current},values:function(){return this.$store.getters["content/values"]()}},watch:{language:function(){this.fetch()}},created:function(){this.fetch()},methods:{input:function(t,e,n){this.$store.dispatch("content/update",[n,t[n]])},fetch:function(){var t=this;this.$api.get(this.parent+"/sections/"+this.name).then(function(e){t.fields=e.fields,kt()(t.fields).forEach(function(e){t.fields[e].section=t.name,t.fields[e].endpoints={field:t.parent+"/fields/"+e,section:t.parent+"/sections/"+t.name,model:t.parent}}),t.isLoading=!1}).catch(function(e){t.issue=e,t.isLoading=!1})},onSubmit:function(t){this.$events.$emit("keydown.cmd.s",t)}}},vh=bh,kh=(n("7d5d"),Object(_["a"])(vh,mh,gh,!1,null,null,null)),$h=kh.exports,_h=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-error-view",{staticClass:"k-browser-view"},[n("p",[t._v("\n We are really sorry, but your browser does not support\n all features required for the Kirby Panel.\n ")]),!1===t.hasFetchSupport?[n("p",[n("strong",[t._v("Fetch")]),n("br"),t._v("\n We use Javascript's new Fetch API. You can find a list of supported browsers for this feature on\n "),n("strong",[n("a",{attrs:{href:"https://caniuse.com/#feat=fetch"}},[t._v("caniuse.com")])])])]:t._e(),!1===t.hasGridSupport?[n("p",[n("strong",[t._v("CSS Grid")]),n("br"),t._v("\n We use CSS Grids for all our layouts. You can find a list of supported browsers for this feature on\n "),n("strong",[n("a",{attrs:{href:"https://caniuse.com/#feat=css-grid"}},[t._v("caniuse.com")])])])]:t._e()],2)},yh=[],xh={grid:function(){return!(!window.CSS||!window.CSS.supports("display","grid"))},fetch:function(){return void 0!==window.fetch},all:function(){return this.fetch()&&this.grid()}},wh={computed:{hasFetchSupport:function(){return xh.fetch()},hasGridSupport:function(){return xh.grid()}},created:function(){this.$store.dispatch("content/current",null),xh.all()&&this.$router.push("/")}},Oh=wh,Ch=(n("d6fc"),Object(_["a"])(Oh,_h,yh,!1,null,null,null)),Sh=Ch.exports,Eh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-error-boundary",{key:t.plugin,scopedSlots:t._u([{key:"error",fn:function(e){var i=e.error;return n("k-error-view",{},[t._v("\n "+t._s(i.message||i)+"\n ")])}}])},[n("k-"+t.plugin+"-plugin-view",{tag:"component"})],1)},jh=[],Th={props:{plugin:String},beforeRouteEnter:function(t,e,n){n(function(t){t.$store.dispatch("breadcrumb",[]),t.$store.dispatch("content/current",null)})},watch:{plugin:{handler:function(){this.$store.dispatch("view",this.plugin)},immediate:!0}}},Ih=Th,Lh=Object(_["a"])(Ih,Eh,jh,!1,null,null,null),qh=Lh.exports,Ah=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-view",{staticClass:"k-error-view"},[n("div",{staticClass:"k-error-view-content"},[n("k-text",[n("p",[n("k-icon",{staticClass:"k-error-view-icon",attrs:{type:"alert"}})],1),n("p",[t._t("default")],2)])],1)])},Nh=[],Bh=(n("d221"),{}),Ph=Object(_["a"])(Bh,Ah,Nh,!1,null,null,null),Dh=Ph.exports,Rh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):n("div",{staticClass:"k-file-view"},[n("k-file-preview",{attrs:{file:t.file}}),n("k-view",{staticClass:"k-file-content",attrs:{"data-locked":t.isLocked}},[n("k-header",{attrs:{editable:t.permissions.changeName&&!t.isLocked,tabs:t.tabs,tab:t.tab},on:{edit:function(e){return t.action("rename")}}},[t._v("\n\n "+t._s(t.file.filename)+"\n\n "),n("k-button-group",{attrs:{slot:"left"},slot:"left"},[n("k-button",{attrs:{responsive:!0,icon:"open"},on:{click:function(e){return t.action("download")}}},[t._v("\n "+t._s(t.$t("open"))+"\n ")]),n("k-dropdown",[n("k-button",{attrs:{responsive:!0,disabled:t.isLocked,icon:"cog"},on:{click:function(e){return t.$refs.settings.toggle()}}},[t._v("\n "+t._s(t.$t("settings"))+"\n ")]),n("k-dropdown-content",{ref:"settings",attrs:{options:t.options},on:{action:t.action}})],1),n("k-languages-dropdown")],1),t.file.id?n("k-prev-next",{attrs:{slot:"right",prev:t.prev,next:t.next},slot:"right"}):t._e()],1),t.file.id?n("k-tabs",{key:t.tabsKey,ref:"tabs",attrs:{parent:t.$api.files.url(t.path,t.file.filename),tabs:t.tabs,blueprint:t.file.blueprint.name},on:{tab:function(e){t.tab=e}}}):t._e(),n("k-file-rename-dialog",{ref:"rename",on:{success:t.renamed}}),n("k-file-remove-dialog",{ref:"remove",on:{success:t.deleted}}),n("k-upload",{ref:"upload",attrs:{url:t.uploadApi,accept:t.file.mime,multiple:!1},on:{success:t.uploaded}})],1)],1)},Mh=[],zh={computed:{isLocked:function(){return null!==this.$store.state.content.status.lock}},created:function(){this.fetch(),this.$events.$on("model.reload",this.fetch),this.$events.$on("keydown.left",this.toPrev),this.$events.$on("keydown.right",this.toNext)},destroyed:function(){this.$events.$off("model.reload",this.fetch),this.$events.$off("keydown.left",this.toPrev),this.$events.$off("keydown.right",this.toNext)},methods:{toPrev:function(t){this.prev&&"body"===t.target.localName&&this.$router.push(this.prev.link)},toNext:function(t){this.next&&"body"===t.target.localName&&this.$router.push(this.next.link)}}},Uh={mixins:[zh],props:{path:{type:String},filename:{type:String,required:!0}},data:function(){return{name:"",file:{id:null,parent:null,filename:"",url:"",prev:null,next:null,panelIcon:null,panelImage:null,mime:null,content:{}},permissions:{changeName:!1,delete:!1},issue:null,tabs:[],tab:null,options:null}},computed:{uploadApi:function(){return A.api+"/"+this.path+"/files/"+this.filename},prev:function(){if(this.file.prev)return{link:this.$api.files.link(this.path,this.file.prev.filename),tooltip:this.file.prev.filename}},tabsKey:function(){return"file-"+this.file.id+"-tabs"},language:function(){return this.$store.state.languages.current},next:function(){if(this.file.next)return{link:this.$api.files.link(this.path,this.file.next.filename),tooltip:this.file.next.filename}}},watch:{language:function(){this.fetch()},filename:function(){this.fetch()}},methods:{fetch:function(){var t=this;this.$api.files.get(this.path,this.filename,{view:"panel"}).then(function(e){t.file=e,t.file.next=e.nextWithTemplate,t.file.prev=e.prevWithTemplate,t.file.url=e.url,t.name=e.name,t.tabs=e.blueprint.tabs,t.permissions=e.options,t.options=function(e){t.$api.files.options(t.path,t.file.filename).then(function(t){e(t)})},t.$store.dispatch("breadcrumb",t.$api.files.breadcrumb(t.file,t.$route.name)),t.$store.dispatch("title",t.filename),t.$store.dispatch("content/create",{id:"files/"+e.id,api:t.$api.files.link(t.path,t.filename),content:e.content})}).catch(function(e){window.console.error(e),t.issue=e})},action:function(t){switch(t){case"download":window.open(this.file.url);break;case"rename":this.$refs.rename.open(this.path,this.file.filename);break;case"replace":this.$refs.upload.open({url:A.api+"/"+this.$api.files.url(this.path,this.file.filename),accept:this.file.mime});break;case"remove":this.$refs.remove.open(this.path,this.file.filename);break}},deleted:function(){this.path?this.$router.push("/"+this.path):this.$router.push("/site")},renamed:function(t){this.$router.push(this.$api.files.link(this.path,t.filename))},uploaded:function(){this.fetch(),this.$store.dispatch("notification/success",":)")}}},Fh=Uh,Hh=Object(_["a"])(Fh,Rh,Mh,!1,null,null,null),Kh=Hh.exports,Vh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.system?n("k-view",{staticClass:"k-installation-view",attrs:{align:"center"}},["install"===t.state?n("form",{on:{submit:function(e){return e.preventDefault(),t.install(e)}}},[n("h1",{staticClass:"k-offscreen"},[t._v(t._s(t.$t("installation")))]),n("k-fieldset",{attrs:{fields:t.fields,novalidate:!0},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}}),n("k-button",{attrs:{type:"submit",icon:"check"}},[t._v(t._s(t.$t("install")))])],1):"completed"===t.state?n("k-text",[n("k-headline",[t._v(t._s(t.$t("installation.completed")))]),n("k-link",{attrs:{to:"/login"}},[t._v(t._s(t.$t("login")))])],1):n("div",[t.system.isInstalled?t._e():n("k-headline",[t._v(t._s(t.$t("installation.issues.headline")))]),n("ul",{staticClass:"k-installation-issues"},[!1===t.system.isInstallable?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.disabled"))}})],1):t._e(),!1===t.requirements.php?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.php"))}})],1):t._e(),!1===t.requirements.server?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.server"))}})],1):t._e(),!1===t.requirements.mbstring?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.mbstring"))}})],1):t._e(),!1===t.requirements.curl?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.curl"))}})],1):t._e(),!1===t.requirements.accounts?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.accounts"))}})],1):t._e(),!1===t.requirements.content?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.content"))}})],1):t._e(),!1===t.requirements.media?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.media"))}})],1):t._e(),!1===t.requirements.sessions?n("li",[n("k-icon",{attrs:{type:"alert"}}),n("span",{domProps:{innerHTML:t._s(t.$t("installation.issues.sessions"))}})],1):t._e()]),n("k-button",{attrs:{icon:"refresh"},on:{click:t.check}},[n("span",{domProps:{innerHTML:t._s(t.$t("retry"))}})])],1)],1):t._e()},Yh=[],Wh={data:function(){return{user:{name:"",email:"",language:"",password:"",role:"admin"},languages:[],system:null}},computed:{state:function(){return this.system.isOk&&this.system.isInstallable&&!this.system.isInstalled?"install":this.system.isOk&&this.system.isInstallable&&this.system.isInstalled?"completed":void 0},translation:function(){return this.$store.state.translation.current},requirements:function(){return this.system&&this.system.requirements?this.system.requirements:{}},fields:function(){return{email:{label:this.$t("email"),type:"email",link:!1,required:!0},password:{label:this.$t("password"),type:"password",placeholder:this.$t("password")+" …",required:!0},language:{label:this.$t("language"),type:"select",options:this.languages,icon:"globe",empty:!1,required:!0}}}},watch:{translation:{handler:function(t){this.user.language=t},immediate:!0},"user.language":function(t){this.$store.dispatch("translation/activate",t)}},created:function(){this.$store.dispatch("content/current",null),this.check()},methods:{install:function(){var t=this;this.$api.system.install(this.user).then(function(e){t.$store.dispatch("user/current",e),t.$store.dispatch("notification/success",t.$t("welcome")+"!"),t.$router.push("/")}).catch(function(e){t.$store.dispatch("notification/error",e)})},check:function(){var t=this;this.$store.dispatch("system/load",!0).then(function(e){!0===e.isInstalled&&e.isReady?t.$router.push("/login"):t.$api.translations.options().then(function(n){t.languages=n,t.system=e,t.$store.dispatch("title",t.$t("view.installation"))})})}}},Gh=Wh,Jh=(n("146c"),Object(_["a"])(Gh,Vh,Yh,!1,null,null,null)),Zh=Jh.exports,Xh=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):t.ready?n("k-view",{staticClass:"k-login-view",attrs:{align:"center"}},[n("k-login-form")],1):t._e()},Qh=[],tm=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("form",{staticClass:"k-login-form",on:{submit:function(e){return e.preventDefault(),t.login(e)}}},[n("h1",{staticClass:"k-offscreen"},[t._v(t._s(t.$t("login")))]),t.issue?n("div",{staticClass:"k-login-alert",on:{click:function(e){t.issue=null}}},[n("span",[t._v(t._s(t.issue))]),n("k-icon",{attrs:{type:"alert"}})],1):t._e(),n("k-fieldset",{attrs:{novalidate:!0,fields:t.fields},model:{value:t.user,callback:function(e){t.user=e},expression:"user"}}),n("div",{staticClass:"k-login-buttons"},[n("span",{staticClass:"k-login-checkbox"},[n("k-checkbox-input",{attrs:{value:t.user.remember,label:t.$t("login.remember")},on:{input:function(e){t.user.remember=e}}})],1),n("k-button",{staticClass:"k-login-button",attrs:{icon:"check",type:"submit"}},[t._v("\n "+t._s(t.$t("login"))+" "),t.isLoading?[t._v("…")]:t._e()],2)],1)],1)},em=[],nm={data:function(){return{isLoading:!1,issue:"",user:{email:"",password:"",remember:!1}}},computed:{fields:function(){return{email:{autofocus:!0,label:this.$t("email"),type:"email",required:!0,link:!1},password:{label:this.$t("password"),type:"password",minLength:8,required:!0,autocomplete:"current-password",counter:!1}}}},methods:{login:function(){var t=this;this.issue=null,this.isLoading=!0,this.$store.dispatch("user/login",this.user).then(function(){t.$store.dispatch("system/load",!0).then(function(){t.$store.dispatch("notification/success",t.$t("welcome")),t.isLoading=!1})}).catch(function(){t.issue=t.$t("error.access.login"),t.isLoading=!1})}}},im=nm,sm=Object(_["a"])(im,tm,em,!1,null,null,null),am=sm.exports,om={components:{"k-login-form":window.panel.plugins.login||am},data:function(){return{ready:!1,issue:null}},created:function(){var t=this;this.$store.dispatch("content/current",null),this.$store.dispatch("system/load").then(function(e){e.isReady||t.$router.push("/installation"),e.user&&e.user.id&&t.$router.push("/"),t.ready=!0,t.$store.dispatch("title",t.$t("login"))}).catch(function(e){t.issue=e})}},rm=om,lm=(n("24c1"),Object(_["a"])(rm,Xh,Qh,!1,null,null,null)),um=lm.exports,cm=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):n("k-view",{staticClass:"k-page-view",attrs:{"data-locked":t.isLocked}},[n("k-header",{attrs:{tabs:t.tabs,tab:t.tab,editable:t.permissions.changeTitle&&!t.isLocked},on:{edit:function(e){return t.action("rename")}}},[t._v("\n "+t._s(t.page.title)+"\n "),n("k-button-group",{attrs:{slot:"left"},slot:"left"},[t.permissions.preview&&t.page.previewUrl?n("k-button",{attrs:{responsive:!0,link:t.page.previewUrl,target:"_blank",icon:"open"}},[t._v("\n "+t._s(t.$t("open"))+"\n ")]):t._e(),t.status?n("k-button",{class:["k-status-flag","k-status-flag-"+t.page.status],attrs:{disabled:!t.permissions.changeStatus||t.isLocked,icon:!t.permissions.changeStatus||t.isLocked?"protected":"circle",responsive:!0,tooltip:t.status.label},on:{click:function(e){return t.action("status")}}},[t._v("\n "+t._s(t.status.label)+"\n ")]):t._e(),n("k-dropdown",[n("k-button",{attrs:{responsive:!0,disabled:!0===t.isLocked,icon:"cog"},on:{click:function(e){return t.$refs.settings.toggle()}}},[t._v("\n "+t._s(t.$t("settings"))+"\n ")]),n("k-dropdown-content",{ref:"settings",attrs:{options:t.options},on:{action:t.action}})],1),n("k-languages-dropdown")],1),t.page.id?n("k-prev-next",{attrs:{slot:"right",prev:t.prev,next:t.next},slot:"right"}):t._e()],1),t.page.id?n("k-tabs",{key:t.tabsKey,ref:"tabs",attrs:{parent:t.$api.pages.url(t.page.id),blueprint:t.blueprint,tabs:t.tabs},on:{tab:t.onTab}}):t._e(),n("k-page-rename-dialog",{ref:"rename",on:{success:t.update}}),n("k-page-duplicate-dialog",{ref:"duplicate"}),n("k-page-url-dialog",{ref:"url"}),n("k-page-status-dialog",{ref:"status",on:{success:t.update}}),n("k-page-template-dialog",{ref:"template",on:{success:t.update}}),n("k-page-remove-dialog",{ref:"remove"})],1)},dm=[],pm={mixins:[zh],props:{path:{type:String,required:!0}},data:function(){return{page:{title:"",id:null,prev:null,next:null,status:null},blueprint:null,preview:!0,permissions:{changeTitle:!1,changeStatus:!1},icon:"page",issue:null,tab:null,tabs:[],options:null}},computed:{language:function(){return this.$store.state.languages.current},next:function(){if(this.page.next)return{link:this.$api.pages.link(this.page.next.id),tooltip:this.page.next.title}},prev:function(){if(this.page.prev)return{link:this.$api.pages.link(this.page.prev.id),tooltip:this.page.prev.title}},status:function(){return null!==this.page.status?this.page.blueprint.status[this.page.status]:null},tabsKey:function(){return"page-"+this.page.id+"-tabs"}},watch:{language:function(){this.fetch()},path:function(){this.fetch()}},created:function(){this.$events.$on("page.changeSlug",this.update)},destroyed:function(){this.$events.$off("page.changeSlug",this.update)},methods:{action:function(t){switch(t){case"duplicate":this.$refs.duplicate.open(this.page.id);break;case"rename":this.$refs.rename.open(this.page.id);break;case"url":this.$refs.url.open(this.page.id);break;case"status":this.$refs.status.open(this.page.id);break;case"template":this.$refs.template.open(this.page.id);break;case"remove":this.$refs.remove.open(this.page.id);break;default:this.$store.dispatch("notification/error",this.$t("notification.notImplemented"));break}},fetch:function(){var t=this;this.$api.pages.get(this.path,{view:"panel"}).then(function(e){t.page=e,t.blueprint=e.blueprint.name,t.permissions=e.options,t.tabs=e.blueprint.tabs,t.options=function(e){t.$api.pages.options(t.page.id).then(function(t){e(t)})},t.$store.dispatch("breadcrumb",t.$api.pages.breadcrumb(e)),t.$store.dispatch("title",t.page.title),t.$store.dispatch("content/create",{id:"pages/"+t.page.id,api:t.$api.pages.link(t.page.id),content:t.page.content})}).catch(function(e){t.issue=e})},onTab:function(t){this.tab=t},update:function(){this.fetch(),this.$emit("model.update")}}},fm=pm,hm=(n("202d"),Object(_["a"])(fm,cm,dm,!1,null,null,null)),mm=hm.exports,gm=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("k-view",{staticClass:"k-settings-view"},[n("k-header",[t._v("\n "+t._s(t.$t("view.settings"))+"\n ")]),n("section",{staticClass:"k-system-info"},[n("header",[n("k-headline",[t._v("Kirby")])],1),n("ul",{staticClass:"k-system-info-box"},[n("li",[n("dl",[n("dt",[t._v(t._s(t.$t("license")))]),n("dd",[t.license?[t._v("\n "+t._s(t.license)+"\n ")]:n("p",[n("strong",{staticClass:"k-system-unregistered"},[t._v(t._s(t.$t("license.unregistered")))])])],2)])]),n("li",[n("dl",[n("dt",[t._v(t._s(t.$t("version")))]),n("dd",[t._v(t._s(t.$store.state.system.info.version))])])])])]),t.multilang?n("section",{staticClass:"k-languages"},[t.languages.length>0?[n("section",{staticClass:"k-languages-section"},[n("header",[n("k-headline",[t._v(t._s(t.$t("languages.default")))])],1),n("k-collection",{attrs:{items:t.defaultLanguage},on:{action:t.action}})],1),n("section",{staticClass:"k-languages-section"},[n("header",[n("k-headline",[t._v(t._s(t.$t("languages.secondary")))]),n("k-button",{attrs:{icon:"add"},on:{click:function(e){return t.$refs.create.open()}}},[t._v(t._s(t.$t("language.create")))])],1),t.translations.length?n("k-collection",{attrs:{items:t.translations},on:{action:t.action}}):n("k-empty",{attrs:{icon:"globe"},on:{click:function(e){return t.$refs.create.open()}}},[t._v(t._s(t.$t("languages.secondary.empty")))])],1)]:0===t.languages.length?[n("header",[n("k-headline",[t._v(t._s(t.$t("languages")))]),n("k-button",{attrs:{icon:"add"},on:{click:function(e){return t.$refs.create.open()}}},[t._v(t._s(t.$t("language.create")))])],1),n("k-empty",{attrs:{icon:"globe"},on:{click:function(e){return t.$refs.create.open()}}},[t._v(t._s(t.$t("languages.empty")))])]:t._e(),n("k-language-create-dialog",{ref:"create",on:{success:t.fetch}}),n("k-language-update-dialog",{ref:"update",on:{success:t.fetch}}),n("k-language-remove-dialog",{ref:"remove",on:{success:t.fetch}})],2):t._e()],1)},bm=[],vm={data:function(){return{languages:[]}},computed:{defaultLanguage:function(){return this.languages.filter(function(t){return t.default})},multilang:function(){return this.$store.state.system.info.multilang},license:function(){return this.$store.state.system.info.license},translations:function(){return this.languages.filter(function(t){return!1===t.default})}},created:function(){this.$store.dispatch("content/current",null),this.$store.dispatch("title",this.$t("view.settings")),this.$store.dispatch("breadcrumb",[]),this.fetch()},methods:{fetch:function(){var t=this;!1!==this.multilang?this.$api.get("languages").then(function(e){t.languages=e.data.map(function(n){return{id:n.code,default:n.default,icon:{type:"globe",back:"black"},text:n.name,info:n.code,options:[{icon:"edit",text:t.$t("edit"),click:"update"},{icon:"trash",text:t.$t("delete"),disabled:n.default&&1!==e.data.length,click:"remove"}]}})}):this.languages=[]},action:function(t,e){switch(e){case"update":this.$refs.update.open(t.id);break;case"remove":this.$refs.remove.open(t.id);break}}}},km=vm,$m=(n("9bd5"),Object(_["a"])(km,gm,bm,!1,null,null,null)),_m=$m.exports,ym=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):n("k-view",{key:"site-view",staticClass:"k-site-view",attrs:{"data-locked":t.isLocked}},[n("k-header",{attrs:{tabs:t.tabs,tab:t.tab,editable:t.permissions.changeTitle&&!t.isLocked},on:{edit:function(e){return t.action("rename")}}},[t._v("\n "+t._s(t.site.title)+"\n "),n("k-button-group",{attrs:{slot:"left"},slot:"left"},[n("k-button",{attrs:{responsive:!0,link:t.site.previewUrl,target:"_blank",icon:"open"}},[t._v("\n "+t._s(t.$t("open"))+"\n ")]),n("k-languages-dropdown")],1)],1),t.site.url?n("k-tabs",{ref:"tabs",attrs:{tabs:t.tabs,blueprint:t.site.blueprint.name,parent:"site"},on:{tab:function(e){t.tab=e}}}):t._e(),n("k-site-rename-dialog",{ref:"rename",on:{success:t.fetch}})],1)},xm=[],wm={data:function(){return{site:{title:null,url:null},issue:null,tab:null,tabs:[],options:null,permissions:{changeTitle:!0}}},computed:{isLocked:function(){return null!==this.$store.state.content.status.lock},language:function(){return this.$store.state.languages.current}},watch:{language:function(){this.fetch()}},created:function(){this.fetch()},methods:{fetch:function(){var t=this;this.$api.site.get({view:"panel"}).then(function(e){t.site=e,t.tabs=e.blueprint.tabs,t.permissions=e.options,t.options=function(e){t.$api.site.options().then(function(t){e(t)})},t.$store.dispatch("breadcrumb",[]),t.$store.dispatch("title",null),t.$store.dispatch("content/create",{id:"site",api:"site",content:e.content})}).catch(function(e){t.issue=e})},action:function(t){switch(t){case"languages":this.$refs.languages.open();break;case"rename":this.$refs.rename.open();break;default:this.$store.dispatch("notification/error",this.$t("notification.notImplemented"));break}}}},Om=wm,Cm=Object(_["a"])(Om,ym,xm,!1,null,null,null),Sm=Cm.exports,Em=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):n("k-view",{staticClass:"k-users-view"},[n("k-header",[t._v("\n "+t._s(t.$t("view.users"))+"\n "),n("k-button-group",{attrs:{slot:"left"},slot:"left"},[n("k-button",{attrs:{disabled:!1===t.$permissions.users.create,icon:"add"},on:{click:function(e){return t.$refs.create.open()}}},[t._v(t._s(t.$t("user.create")))])],1),n("k-button-group",{attrs:{slot:"right"},slot:"right"},[n("k-dropdown",[n("k-button",{attrs:{responsive:!0,icon:"funnel"},on:{click:function(e){return t.$refs.roles.toggle()}}},[t._v("\n "+t._s(t.$t("role"))+": "+t._s(t.role?t.role.text:t.$t("role.all"))+"\n ")]),n("k-dropdown-content",{ref:"roles",attrs:{align:"right"}},[n("k-dropdown-item",{attrs:{icon:"bolt"},on:{click:function(e){return t.filter(!1)}}},[t._v("\n "+t._s(t.$t("role.all"))+"\n ")]),n("hr"),t._l(t.roles,function(e){return n("k-dropdown-item",{key:e.value,attrs:{icon:"bolt"},on:{click:function(n){return t.filter(e)}}},[t._v("\n "+t._s(e.text)+"\n ")])})],2)],1)],1)],1),t.users.length>0?[n("k-collection",{attrs:{items:t.users,pagination:t.pagination},on:{paginate:t.paginate,action:t.action}})]:0===t.total?[n("k-empty",{attrs:{icon:"users"}},[t._v(t._s(t.$t("role.empty")))])]:t._e(),n("k-user-create-dialog",{ref:"create",on:{success:t.fetch}}),n("k-user-email-dialog",{ref:"email",on:{success:t.fetch}}),n("k-user-language-dialog",{ref:"language",on:{success:t.fetch}}),n("k-user-password-dialog",{ref:"password"}),n("k-user-remove-dialog",{ref:"remove",on:{success:t.fetch}}),n("k-user-rename-dialog",{ref:"rename",on:{success:t.fetch}}),n("k-user-role-dialog",{ref:"role",on:{success:t.fetch}})],2)},jm=[],Tm={data:function(){return{page:1,limit:20,total:null,users:[],roles:[],issue:null}},computed:{pagination:function(){return{page:this.page,limit:this.limit,total:this.total}},role:function(){var t=this,e=null;return this.$route.params.role&&this.roles.forEach(function(n){n.value===t.$route.params.role&&(e=n)}),e}},watch:{$route:function(){this.fetch()}},created:function(){var t=this;this.$store.dispatch("content/current",null),this.$api.roles.options().then(function(e){t.roles=e,t.fetch()})},methods:{fetch:function(){var t=this;this.$store.dispatch("title",this.$t("view.users"));var e={paginate:{page:this.page,limit:this.limit},sortBy:"username asc"};this.role&&(e.filterBy=[{field:"role",operator:"==",value:this.role.value}]),this.$api.users.list(e).then(function(e){t.users=e.data.map(function(e){var n={id:e.id,icon:{type:"user",back:"black"},text:e.name||e.email,info:e.role.title,link:"/users/"+e.id,options:function(n){t.$api.users.options(e.id,"list").then(function(t){return n(t)}).catch(function(e){t.$store.dispatch("notification/error",e)})},image:null};return e.avatar&&(n.image={url:e.avatar.url,cover:!0}),n}),t.role?t.$store.dispatch("breadcrumb",[{link:"/users/role/"+t.role.value,label:t.$t("role")+": "+t.role.text}]):t.$store.dispatch("breadcrumb",[]),t.total=e.pagination.total}).catch(function(e){t.issue=e})},paginate:function(t){this.page=t.page,this.limit=t.limit,this.fetch()},action:function(t,e){switch(e){case"edit":this.$router.push("/users/"+t.id);break;case"email":this.$refs.email.open(t.id);break;case"role":this.$refs.role.open(t.id);break;case"rename":this.$refs.rename.open(t.id);break;case"password":this.$refs.password.open(t.id);break;case"language":this.$refs.language.open(t.id);break;case"remove":this.$refs.remove.open(t.id);break}},filter:function(t){!1===t?this.$router.push("/users"):this.$router.push("/users/role/"+t.value),this.$refs.roles.close()}}},Im=Tm,Lm=Object(_["a"])(Im,Em,jm,!1,null,null,null),qm=Lm.exports,Am=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.issue?n("k-error-view",[t._v("\n "+t._s(t.issue.message)+"\n")]):t.ready?n("div",{staticClass:"k-user-view",attrs:{"data-locked":t.isLocked}},[n("div",{staticClass:"k-user-profile"},[n("k-view",[t.avatar?[n("k-dropdown",[n("k-button",{staticClass:"k-user-view-image",attrs:{tooltip:t.$t("avatar"),disabled:t.isLocked},on:{click:function(e){return t.$refs.picture.toggle()}}},[t.avatar?n("k-image",{attrs:{cover:!0,src:t.avatar,ratio:"1/1"}}):t._e()],1),n("k-dropdown-content",{ref:"picture"},[n("k-dropdown-item",{attrs:{icon:"upload"},on:{click:function(e){return t.$refs.upload.open()}}},[t._v("\n "+t._s(t.$t("change"))+"\n ")]),n("k-dropdown-item",{attrs:{icon:"trash"},on:{click:function(e){return t.action("picture.delete")}}},[t._v("\n "+t._s(t.$t("delete"))+"\n ")])],1)],1)]:[n("k-button",{staticClass:"k-user-view-image",attrs:{tooltip:t.$t("avatar")},on:{click:function(e){return t.$refs.upload.open()}}},[n("k-icon",{attrs:{type:"user"}})],1)],n("k-button-group",[n("k-button",{attrs:{disabled:!t.permissions.changeEmail||t.isLocked,icon:"email"},on:{click:function(e){return t.action("email")}}},[t._v(t._s(t.$t("email"))+": "+t._s(t.user.email))]),n("k-button",{attrs:{disabled:!t.permissions.changeRole||t.isLocked,icon:"bolt"},on:{click:function(e){return t.action("role")}}},[t._v(t._s(t.$t("role"))+": "+t._s(t.user.role.title))]),n("k-button",{attrs:{disabled:!t.permissions.changeLanguage||t.isLocked,icon:"globe"},on:{click:function(e){return t.action("language")}}},[t._v(t._s(t.$t("language"))+": "+t._s(t.user.language))])],1)],2)],1),n("k-view",[n("k-header",{attrs:{editable:t.permissions.changeName&&!t.isLocked,tabs:t.tabs,tab:t.tab},on:{edit:function(e){return t.action("rename")}}},[t.user.name&&0!==t.user.name.length?[t._v(t._s(t.user.name))]:n("span",{staticClass:"k-user-name-placeholder"},[t._v(t._s(t.$t("name"))+" …")]),n("k-button-group",{attrs:{slot:"left"},slot:"left"},[n("k-dropdown",[n("k-button",{attrs:{disabled:t.isLocked,icon:"cog"},on:{click:function(e){return t.$refs.settings.toggle()}}},[t._v("\n "+t._s(t.$t("settings"))+"\n ")]),n("k-dropdown-content",{ref:"settings",attrs:{options:t.options},on:{action:t.action}})],1),n("k-languages-dropdown")],1),t.user.id&&"User"===t.$route.name?n("k-prev-next",{attrs:{slot:"right",prev:t.prev,next:t.next},slot:"right"}):t._e()],2),t.user&&t.tabs.length?n("k-tabs",{key:t.tabsKey,ref:"tabs",attrs:{parent:"users/"+t.user.id,blueprint:t.user.blueprint.name,tabs:t.tabs},on:{tab:function(e){t.tab=e}}}):t.ready?n("k-box",{attrs:{text:t.$t("user.blueprint",{role:t.user.role.name}),theme:"info"}}):t._e(),n("k-user-email-dialog",{ref:"email",on:{success:t.fetch}}),n("k-user-language-dialog",{ref:"language",on:{success:t.fetch}}),n("k-user-password-dialog",{ref:"password"}),n("k-user-remove-dialog",{ref:"remove"}),n("k-user-rename-dialog",{ref:"rename",on:{success:t.fetch}}),n("k-user-role-dialog",{ref:"role",on:{success:t.fetch}}),n("k-upload",{ref:"upload",attrs:{url:t.uploadApi,multiple:!1,accept:"image/*"},on:{success:t.uploadedAvatar}})],1)],1):t._e()},Nm=[],Bm={mixins:[zh],props:{id:{type:String,required:!0}},data:function(){return{tab:null,tabs:[],ready:!1,user:{role:{name:null},name:null,language:null,prev:null,next:null},permissions:{changeEmail:!0,changeName:!0,changeLanguage:!0,changeRole:!0},issue:null,avatar:null,options:null}},computed:{language:function(){return this.$store.state.languages.current},next:function(){if(this.user.next)return{link:this.$api.users.link(this.user.next.id),tooltip:this.user.next.name}},prev:function(){if(this.user.prev)return{link:this.$api.users.link(this.user.prev.id),tooltip:this.user.prev.name}},tabsKey:function(){return"user-"+this.user.id+"-tabs"},uploadApi:function(){return A.api+"/users/"+this.user.id+"/avatar"}},watch:{language:function(){this.fetch()},id:function(){this.fetch()}},methods:{action:function(t){var e=this;switch(t){case"email":this.$refs.email.open(this.user.id);break;case"language":this.$refs.language.open(this.user.id);break;case"password":this.$refs.password.open(this.user.id);break;case"picture.delete":this.$api.users.deleteAvatar(this.id).then(function(){e.$store.dispatch("notification/success",":)"),e.avatar=null});break;case"remove":this.$refs.remove.open(this.user.id);break;case"rename":this.$refs.rename.open(this.user.id);break;case"role":this.$refs.role.open(this.user.id);break;default:this.$store.dispatch("notification/error","Not yet implemented")}},fetch:function(){var t=this;this.$api.users.get(this.id,{view:"panel"}).then(function(e){t.user=e,t.tabs=e.blueprint.tabs,t.ready=!0,t.permissions=e.options,t.options=function(e){t.$api.users.options(t.user.id).then(function(t){e(t)})},e.avatar?t.avatar=e.avatar.url:t.avatar=null,"User"===t.$route.name?t.$store.dispatch("breadcrumb",t.$api.users.breadcrumb(e)):t.$store.dispatch("breadcrumb",[]),t.$store.dispatch("title",t.user.name||t.user.email),t.$store.dispatch("content/create",{id:"users/"+e.id,api:t.$api.users.link(e.id),content:e.content})}).catch(function(e){t.issue=e})},uploadedAvatar:function(){this.$store.dispatch("notification/success",":)"),this.fetch()}}},Pm=Bm,Dm=(n("bd96"),Object(_["a"])(Pm,Am,Nm,!1,null,null,null)),Rm=Dm.exports;z["a"].component("k-dialog",Z),z["a"].component("k-error-dialog",it),z["a"].component("k-file-rename-dialog",mt),z["a"].component("k-file-remove-dialog",ut),z["a"].component("k-files-dialog",jt),z["a"].component("k-language-create-dialog",Nt),z["a"].component("k-language-remove-dialog",zt),z["a"].component("k-language-update-dialog",Wt),z["a"].component("k-page-create-dialog",te),z["a"].component("k-page-duplicate-dialog",oe),z["a"].component("k-page-rename-dialog",ve),z["a"].component("k-page-remove-dialog",pe),z["a"].component("k-page-status-dialog",we),z["a"].component("k-page-template-dialog",Te),z["a"].component("k-page-url-dialog",Be),z["a"].component("k-pages-dialog",Ue),z["a"].component("k-site-rename-dialog",Ve),z["a"].component("k-user-create-dialog",tn),z["a"].component("k-user-email-dialog",rn),z["a"].component("k-user-language-dialog",fn),z["a"].component("k-user-password-dialog",kn),z["a"].component("k-user-remove-dialog",On),z["a"].component("k-user-rename-dialog",In),z["a"].component("k-user-role-dialog",Pn),z["a"].component("k-users-dialog",Fn),z["a"].component("k-calendar",ei),z["a"].component("k-counter",ri),z["a"].component("k-autocomplete",Gn),z["a"].component("k-form",fi),z["a"].component("k-form-buttons",$i),z["a"].component("k-form-indicator",Ci),z["a"].component("k-field",Li),z["a"].component("k-fieldset",Di),z["a"].component("k-input",Hi),z["a"].component("k-upload",Xi),z["a"].component("k-checkbox-input",as),z["a"].component("k-checkboxes-input",ds),z["a"].component("k-date-input",ks),z["a"].component("k-datetime-input",Os),z["a"].component("k-email-input",Ns),z["a"].component("k-multiselect-input",zs),z["a"].component("k-number-input",Gs),z["a"].component("k-password-input",Qs),z["a"].component("k-radio-input",aa),z["a"].component("k-range-input",da),z["a"].component("k-select-input",ba),z["a"].component("k-tags-input",xa),z["a"].component("k-tel-input",Sa),z["a"].component("k-text-input",Is),z["a"].component("k-textarea-input",qa),z["a"].component("k-time-input",Ra),z["a"].component("k-toggle-input",Ka),z["a"].component("k-url-input",Ga),z["a"].component("k-checkboxes-field",eo),z["a"].component("k-date-field",ro),z["a"].component("k-email-field",ho),z["a"].component("k-files-field",_o),z["a"].component("k-headline-field",So),z["a"].component("k-info-field",qo),z["a"].component("k-line-field",Do),z["a"].component("k-multiselect-field",Ho),z["a"].component("k-number-field",Jo),z["a"].component("k-pages-field",nr),z["a"].component("k-password-field",lr),z["a"].component("k-radio-field",hr),z["a"].component("k-range-field",$r),z["a"].component("k-select-field",Cr),z["a"].component("k-structure-field",Br),z["a"].component("k-tags-field",Ur),z["a"].component("k-text-field",tl),z["a"].component("k-textarea-field",ol),z["a"].component("k-tel-field",Wr),z["a"].component("k-time-field",pl),z["a"].component("k-toggle-field",vl),z["a"].component("k-url-field",wl),z["a"].component("k-users-field",Tl),z["a"].component("k-toolbar",Pl),z["a"].component("k-toolbar-email-dialog",Fl),z["a"].component("k-toolbar-link-dialog",Gl),z["a"].component("k-email-field-preview",pu),z["a"].component("k-files-field-preview",nu),z["a"].component("k-pages-field-preview",vu),z["a"].component("k-toggle-field-preview",wu),z["a"].component("k-url-field-preview",lu),z["a"].component("k-users-field-preview",Tu),z["a"].component("k-bar",Nu),z["a"].component("k-box",zu),z["a"].component("k-card",Yu),z["a"].component("k-cards",Qu),z["a"].component("k-collection",ac),z["a"].component("k-column",dc),z["a"].component("k-dropzone",bc),z["a"].component("k-empty",xc),z["a"].component("k-file-preview",jc),z["a"].component("k-grid",Nc),z["a"].component("k-header",zc),z["a"].component("k-list",Yc),z["a"].component("k-list-item",Qc),z["a"].component("k-tabs",ad),z["a"].component("k-view",dd),z["a"].component("k-draggable",kd),z["a"].component("k-error-boundary",xd),z["a"].component("k-headline",jd),z["a"].component("k-icon",Nd),z["a"].component("k-image",zd),z["a"].component("k-progress",Yd),z["a"].component("k-sort-handle",Xd),z["a"].component("k-text",sp),z["a"].component("k-button",cp),z["a"].component("k-button-disabled",gp),z["a"].component("k-button-group",_p),z["a"].component("k-button-link",Sp),z["a"].component("k-button-native",Ap),z["a"].component("k-dropdown",Rp),z["a"].component("k-dropdown-content",Vp),z["a"].component("k-dropdown-item",Xp),z["a"].component("k-languages-dropdown",df),z["a"].component("k-link",af),z["a"].component("k-pagination",bf),z["a"].component("k-prev-next",xf),z["a"].component("k-search",jf),z["a"].component("k-tag",Nf),z["a"].component("k-topbar",Uf),z["a"].component("k-sections",Wf),z["a"].component("k-info-section",eh),z["a"].component("k-pages-section",lh),z["a"].component("k-files-section",hh),z["a"].component("k-fields-section",$h),z["a"].component("k-browser-view",Sh),z["a"].component("k-custom-view",qh),z["a"].component("k-error-view",Dh),z["a"].component("k-file-view",Kh),z["a"].component("k-installation-view",Zh),z["a"].component("k-login-view",um),z["a"].component("k-page-view",mm),z["a"].component("k-settings-view",_m),z["a"].component("k-site-view",Sm),z["a"].component("k-users-view",qm),z["a"].component("k-user-view",Rm);var Mm={user:function(){return hg.get("auth")},login:function(t){var e={long:t.remember||!1,email:t.email,password:t.password};return hg.post("auth/login",e).then(function(t){return t.user})},logout:function(){return hg.post("auth/logout")}},zm={get:function(t,e,n){return hg.get(this.url(t,e),n).then(function(t){return!0===xt()(t.content)&&(t.content={}),t})},update:function(t,e,n){return hg.patch(this.url(t,e),n)},rename:function(t,e,n){return hg.patch(this.url(t,e,"name"),{name:n})},url:function(t,e,n){var i=t+"/files/"+e;return n&&(i+="/"+n),i},link:function(t,e,n){return"/"+this.url(t,e,n)},delete:function(t,e){return hg.delete(this.url(t,e))},options:function(t,e,n){return hg.get(this.url(t,e),{select:"options"}).then(function(t){var e=t.options,i=[];return"list"===n&&i.push({icon:"open",text:z["a"].i18n.translate("open"),click:"download"}),i.push({icon:"title",text:z["a"].i18n.translate("rename"),click:"rename",disabled:!e.changeName}),i.push({icon:"upload",text:z["a"].i18n.translate("replace"),click:"replace",disabled:!e.replace}),i.push({icon:"trash",text:z["a"].i18n.translate("delete"),click:"remove",disabled:!e.delete}),i})},breadcrumb:function(t,e){var n=null,i=[];switch(e){case"UserFile":i.push({label:t.parent.username,link:hg.users.link(t.parent.id)}),n="users/"+t.parent.id;break;case"SiteFile":n="site";break;case"PageFile":i=t.parents.map(function(t){return{label:t.title,link:hg.pages.link(t.id)}}),n=hg.pages.url(t.parent.id);break}return i.push({label:t.filename,link:this.link(n,t.filename)}),i}},Um={create:function(t,e){return null===t||"/"===t?hg.post("site/children",e):hg.post(this.url(t,"children"),e)},duplicate:function(t,e,n){return hg.post(this.url(t,"duplicate"),{slug:e,children:n.children||!1,files:n.files||!1})},url:function(t,e){var n=null===t?"pages":"pages/"+t.replace(/\//g,"+");return e&&(n+="/"+e),n},link:function(t){return"/"+this.url(t)},get:function(t,e){return hg.get(this.url(t),e).then(function(t){return!0===xt()(t.content)&&(t.content={}),t})},options:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"view";return hg.get(this.url(t),{select:"options"}).then(function(t){var n=t.options,i=[];return"list"===e&&(i.push({click:"preview",icon:"open",text:z["a"].i18n.translate("open"),disabled:!1===n.preview}),i.push("-")),i.push({click:"rename",icon:"title",text:z["a"].i18n.translate("rename"),disabled:!n.changeTitle}),i.push({click:"duplicate",icon:"copy",text:z["a"].i18n.translate("duplicate"),disabled:!n.duplicate}),i.push("-"),i.push({click:"url",icon:"url",text:z["a"].i18n.translate("page.changeSlug"),disabled:!n.changeSlug}),i.push({click:"status",icon:"preview",text:z["a"].i18n.translate("page.changeStatus"),disabled:!n.changeStatus}),i.push({click:"template",icon:"template",text:z["a"].i18n.translate("page.changeTemplate"),disabled:!n.changeTemplate}),i.push("-"),i.push({click:"remove",icon:"trash",text:z["a"].i18n.translate("delete"),disabled:!n.delete}),i})},preview:function(t){return this.get(t,{select:"previewUrl"}).then(function(t){return t.previewUrl})},update:function(t,e){return hg.patch(this.url(t),e)},children:function(t,e){return hg.post(this.url(t,"children/search"),e)},files:function(t,e){return hg.post(this.url(t,"files/search"),e)},delete:function(t,e){return hg.delete(this.url(t),e)},slug:function(t,e){return hg.patch(this.url(t,"slug"),{slug:e})},title:function(t,e){return hg.patch(this.url(t,"title"),{title:e})},template:function(t,e){return hg.patch(this.url(t,"template"),{template:e})},search:function(t,e){return t?hg.post("pages/"+t.replace("/","+")+"/children/search?select=id,title,hasChildren",e):hg.post("site/children/search?select=id,title,hasChildren",e)},status:function(t,e,n){return hg.patch(this.url(t,"status"),{status:e,position:n})},breadcrumb:function(t){var e=this,n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=t.parents.map(function(t){return{label:t.title,link:e.link(t.id)}});return!0===n&&i.push({label:t.title,link:this.link(t.id)}),i}},Fm=n("f499"),Hm=n.n(Fm),Km=n("2f62"),Vm=n("768b"),Ym=function(t){if(void 0!==t)return JSON.parse(Hm()(t))},Wm=function(t,e){localStorage.setItem("kirby$content$"+t,Hm()(e))},Gm={namespaced:!0,state:{current:null,models:{},status:{enabled:!0,lock:null,unlock:null}},getters:{exists:function(t){return function(e){return t.models.hasOwnProperty(e)}},hasChanges:function(t,e){return function(t){var n=e.model(t).changes;return kt()(n).length>0}},isCurrent:function(t){return function(e){return t.current===e}},id:function(t,e,n){return function(e){return e=e||t.current,n.languages.current?e+"/"+n.languages.current.code:e}},model:function(t,e){return function(n){return n=n||t.current,!0===e.exists(n)?t.models[n]:{api:null,originals:{},values:{},changes:{}}}},originals:function(t,e){return function(t){return Ym(e.model(t).originals)}},values:function(t,e){return function(t){return Object(I["a"])({},e.originals(t),e.changes(t))}},changes:function(t,e){return function(t){return Ym(e.model(t).changes)}}},mutations:{CREATE:function(t,e){var n=Object(Vm["a"])(e,2),i=n[0],s=n[1];if(!s)return!1;var a=t.models[i]?t.models[i].changes:s.changes;z["a"].set(t.models,i,{api:s.api,originals:s.originals,changes:a||{}})},CURRENT:function(t,e){t.current=e},LOCK:function(t,e){z["a"].set(t.status,"lock",e)},MOVE:function(t,e){var n=Object(Vm["a"])(e,2),i=n[0],s=n[1],a=Ym(t.models[i]);z["a"].delete(t.models,i),z["a"].set(t.models,s,a);var o=localStorage.getItem("kirby$content$"+i);localStorage.removeItem("kirby$content$"+i),localStorage.setItem("kirby$content$"+s,o)},REMOVE:function(t,e){z["a"].delete(t.models,e),localStorage.removeItem("kirby$content$"+e)},REVERT:function(t,e){t.models[e]&&(z["a"].set(t.models[e],"changes",{}),localStorage.removeItem("kirby$content$"+e))},STATUS:function(t,e){z["a"].set(t.status,"enabled",e)},UNLOCK:function(t,e){e&&z["a"].set(t.models[t.current],"changes",{}),z["a"].set(t.status,"unlock",e)},UPDATE:function(t,e){var n=Object(Vm["a"])(e,3),i=n[0],s=n[1],a=n[2];if(!t.models[i])return!1;a=Ym(a);var o=Hm()(a),r=Hm()(t.models[i].originals[s]);r===o?z["a"].delete(t.models[i].changes,s):z["a"].set(t.models[i].changes,s,a),Wm(i,{api:t.models[i].api,originals:t.models[i].originals,changes:t.models[i].changes})}},actions:{init:function(t){kt()(localStorage).filter(function(t){return t.startsWith("kirby$content$")}).map(function(t){return t.split("kirby$content$")[1]}).forEach(function(e){var n=localStorage.getItem("kirby$content$"+e);t.commit("CREATE",[e,JSON.parse(n)])}),kt()(localStorage).filter(function(t){return t.startsWith("kirby$form$")}).map(function(t){return t.split("kirby$form$")[1]}).forEach(function(e){var n=localStorage.getItem("kirby$form$"+e),i=null;try{i=JSON.parse(n)}catch(a){}if(!i||!i.api)return localStorage.removeItem("kirby$form$"+e),!1;var s={api:i.api,originals:i.originals,changes:i.values};t.commit("CREATE",[e,s]),Wm(e,s),localStorage.removeItem("kirby$form$"+e)})},create:function(t,e){e.id=t.getters.id(e.id),(e.id.startsWith("pages/")||e.id.startsWith("site"))&&delete e.content.title;var n={api:e.api,originals:Ym(e.content),changes:{}};hg.get(e.api+"/unlock").then(function(n){!0===n.supported&&!0===n.unlocked&&t.commit("UNLOCK",t.state.models[e.id].changes)}).catch(function(){}),t.commit("CREATE",[e.id,n]),t.dispatch("current",e.id)},current:function(t,e){t.commit("CURRENT",e)},disable:function(t){t.commit("STATUS",!1)},enable:function(t){t.commit("STATUS",!0)},lock:function(t,e){t.commit("LOCK",e)},move:function(t,e){var n=Object(Vm["a"])(e,2),i=n[0],s=n[1];i=t.getters.id(i),s=t.getters.id(s),t.commit("MOVE",[i,s])},remove:function(t,e){t.commit("REMOVE",e),t.getters.isCurrent(e)&&t.commit("CURRENT",null)},revert:function(t,e){e=e||t.state.current,t.commit("REVERT",e)},save:function(t,e){if(e=e||t.state.current,t.getters.isCurrent(e)&&!1===t.state.status.enabled)return!1;t.dispatch("disable");var n=t.getters.model(e),i=Object(I["a"])({},n.originals,n.changes);return hg.patch(n.api,i).then(function(){t.commit("CREATE",[e,Object(I["a"])({},n,{originals:i})]),t.dispatch("revert",e),t.dispatch("enable")}).catch(function(e){throw t.dispatch("enable"),e})},unlock:function(t,e){t.commit("UNLOCK",e)},update:function(t,e){var n=Object(Vm["a"])(e,3),i=n[0],s=n[1],a=n[2];a=a||t.state.current,t.commit("UPDATE",[a,i,s])}}},Jm={namespaced:!0,state:{instance:null,clock:0,step:5,beats:[]},mutations:{ADD:function(t,e){t.beats.push(e)},CLEAR:function(t){clearInterval(t.instance),t.clock=0},CLOCK:function(t){t.clock+=t.step},INITIALIZE:function(t,e){t.instance=e},REMOVE:function(t,e){var n=t.beats.map(function(t){return t.handler}).indexOf(e);-1!==n&&z["a"].delete(t.beats,n)}},actions:{add:function(t,e){e={handler:e[0]||e,interval:e[1]||t.state.step},e.handler(),t.commit("ADD",e),1===t.state.beats.length&&t.dispatch("run")},clear:function(t){t.commit("CLEAR")},remove:function(t,e){t.commit("REMOVE",e),t.state.beats.length<1&&t.commit("CLEAR")},run:function(t){t.commit("CLEAR"),t.commit("INITIALIZE",setInterval(function(){t.commit("CLOCK"),t.state.beats.forEach(function(e){t.state.clock%e.interval===0&&e.handler()})},1e3*t.state.step))}}},Zm={namespaced:!0,state:{all:[],current:null,default:null},mutations:{SET_ALL:function(t,e){t.all=e.map(function(t){return{code:t.code,default:t.default,direction:t.direction,locale:t.locale,name:t.name,rules:t.rules,url:t.url}})},SET_CURRENT:function(t,e){t.current=e,e&&e.code&&localStorage.setItem("kirby$language",e.code)},SET_DEFAULT:function(t,e){t.default=e}},actions:{current:function(t,e){t.commit("SET_CURRENT",e)},install:function(t,e){var n=e.filter(function(t){return t.default})[0];t.commit("SET_ALL",e),t.commit("SET_DEFAULT",n);var i=localStorage.getItem("kirby$language");if(i){var s=e.filter(function(t){return t.code===i})[0];if(s)return void t.dispatch("current",s)}t.dispatch("current",n||e[0]||null)},load:function(t){return hg.get("languages").then(function(e){t.dispatch("install",e.data)})}}},Xm={timer:null,namespaced:!0,state:{type:null,message:null,details:null,timeout:null},mutations:{SET:function(t,e){t.type=e.type,t.message=e.message,t.details=e.details,t.timeout=e.timeout},UNSET:function(t){t.type=null,t.message=null,t.details=null,t.timeout=null}},actions:{close:function(t){clearTimeout(this.timer),t.commit("UNSET")},open:function(t,e){t.dispatch("close"),t.commit("SET",e),e.timeout&&(this.timer=setTimeout(function(){t.dispatch("close")},e.timeout))},success:function(t,e){"string"===typeof e&&(e={message:e}),t.dispatch("open",Object(I["a"])({type:"success",timeout:4e3},e))},error:function(t,e){"string"===typeof e&&(e={message:e}),t.dispatch("open",Object(I["a"])({type:"error"},e))}}},Qm={namespaced:!0,state:{info:{title:null}},mutations:{SET_INFO:function(t,e){t.info=e},SET_LICENSE:function(t,e){t.info.license=e},SET_TITLE:function(t,e){t.info.title=e}},actions:{title:function(t,e){t.commit("SET_TITLE",e)},register:function(t,e){t.commit("SET_LICENSE",e)},load:function(t,e){return!e&&t.state.info.isReady&&t.rootState.user.current?new Je.a(function(e){e(t.state.info)}):hg.system.info({view:"panel"}).then(function(e){return t.commit("SET_INFO",Object(I["a"])({isReady:e.isInstalled&&e.isOk},e)),e.languages&&t.dispatch("languages/install",e.languages,{root:!0}),t.dispatch("translation/install",e.translation,{root:!0}),t.dispatch("translation/activate",e.translation.id,{root:!0}),e.user&&t.dispatch("user/current",e.user,{root:!0}),t.state.info}).catch(function(e){t.commit("SET_INFO",{isBroken:!0,error:e.message})})}}},tg={namespaced:!0,state:{current:null,installed:[]},mutations:{SET_CURRENT:function(t,e){t.current=e},INSTALL:function(t,e){t.installed[e.id]=e}},actions:{load:function(t,e){return hg.translations.get(e)},install:function(t,e){t.commit("INSTALL",e),z["a"].i18n.add(e.id,e.data)},activate:function(t,e){var n=t.state.installed[e];n?(z["a"].i18n.set(e),t.commit("SET_CURRENT",e),document.dir=n.direction,document.documentElement.lang=e):t.dispatch("load",e).then(function(n){t.dispatch("install",n),t.dispatch("activate",e)})}}},eg=n("8c4f"),ng=function(t,e,n){rg.dispatch("system/load").then(function(){var e=rg.state.user.current;if(!e)return rg.dispatch("user/visit",t.path),rg.dispatch("user/logout"),!1;var i=e.permissions.access;return!1===i.panel?(window.location.href=A.site,!1):!1===i[t.meta.view]?(rg.dispatch("notification/error",{message:z["a"].i18n.translate("error.access.view")}),n("/")):void n()})},ig=[{path:"/",name:"Home",redirect:"/site"},{path:"/browser",name:"Browser",component:z["a"].component("k-browser-view"),meta:{outside:!0}},{path:"/login",component:z["a"].component("k-login-view"),meta:{outside:!0}},{path:"/logout",beforeEnter:function(){kt()(localStorage).forEach(function(t){t.startsWith("kirby$content$")&&localStorage.removeItem(t)}),rg.dispatch("user/logout")},meta:{outside:!0}},{path:"/installation",component:z["a"].component("k-installation-view"),meta:{outside:!0}},{path:"/site",name:"Site",meta:{view:"site"},component:z["a"].component("k-site-view"),beforeEnter:ng},{path:"/site/files/:filename",name:"SiteFile",meta:{view:"site"},component:z["a"].component("k-file-view"),beforeEnter:ng,props:function(t){return{path:"site",filename:t.params.filename}}},{path:"/pages/:path/files/:filename",name:"PageFile",meta:{view:"site"},component:z["a"].component("k-file-view"),beforeEnter:ng,props:function(t){return{path:"pages/"+t.params.path,filename:t.params.filename}}},{path:"/users/:path/files/:filename",name:"UserFile",meta:{view:"users"},component:z["a"].component("k-file-view"),beforeEnter:ng,props:function(t){return{path:"users/"+t.params.path,filename:t.params.filename}}},{path:"/pages/:path",name:"Page",meta:{view:"site"},component:z["a"].component("k-page-view"),beforeEnter:ng,props:function(t){return{path:t.params.path}}},{path:"/settings",name:"Settings",meta:{view:"settings"},component:z["a"].component("k-settings-view"),beforeEnter:ng},{path:"/users/role/:role",name:"UsersByRole",meta:{view:"users"},component:z["a"].component("k-users-view"),beforeEnter:ng,props:function(t){return{role:t.params.role}}},{path:"/users",name:"Users",meta:{view:"users"},beforeEnter:ng,component:z["a"].component("k-users-view")},{path:"/users/:id",name:"User",meta:{view:"users"},component:z["a"].component("k-user-view"),beforeEnter:ng,props:function(t){return{id:t.params.id}}},{path:"/account",name:"Account",meta:{view:"account"},component:z["a"].component("k-user-view"),beforeEnter:ng,props:function(){return{id:rg.state.user.current?rg.state.user.current.id:null}}},{path:"/plugins/:id",name:"Plugin",meta:{view:"plugin"},props:function(t){return{plugin:t.params.id}},beforeEnter:ng,component:z["a"].component("k-custom-view")},{path:"*",name:"NotFound",beforeEnter:function(t,e,n){n("/")}}];z["a"].use(eg["a"]);var sg=new eg["a"]({mode:"history",routes:ig,url:"/"===A.url?"":A.url});sg.beforeEach(function(t,e,n){"Browser"!==t.name&&!1===xh.all()&&n("/browser"),t.meta.outside||rg.dispatch("user/visit",t.path),rg.dispatch("view",t.meta.view),rg.dispatch("content/lock",null),rg.dispatch("content/unlock",null),rg.dispatch("heartbeat/clear"),n()});var ag=sg,og={namespaced:!0,state:{current:null,path:null},mutations:{SET_CURRENT:function(t,e){t.current=e,e&&e.permissions?(z["a"].prototype.$user=e,z["a"].prototype.$permissions=e.permissions):(z["a"].prototype.$user=null,z["a"].prototype.$permissions=null)},SET_PATH:function(t,e){t.path=e}},actions:{current:function(t,e){t.commit("SET_CURRENT",e)},email:function(t,e){t.commit("SET_CURRENT",Object(I["a"])({},t.state.current,{email:e}))},language:function(t,e){t.dispatch("translation/activate",e,{root:!0}),t.commit("SET_CURRENT",Object(I["a"])({},t.state.current,{language:e}))},load:function(t){return hg.auth.user().then(function(e){return t.commit("SET_CURRENT",e),e})},login:function(t,e){return hg.auth.login(e).then(function(e){return t.commit("SET_CURRENT",e),t.dispatch("translation/activate",e.language,{root:!0}),ag.push(t.state.path||"/"),e})},logout:function(t,e){t.commit("SET_CURRENT",null),e?window.location.href=(window.panel.url||"")+"/login":hg.auth.logout().then(function(){ag.push("/login")}).catch(function(){ag.push("/login")})},name:function(t,e){t.commit("SET_CURRENT",Object(I["a"])({},t.state.current,{name:e}))},visit:function(t,e){t.commit("SET_PATH",e)}}};z["a"].use(Km["a"]);var rg=new Km["a"].Store({strict:!1,state:{breadcrumb:[],dialog:null,drag:null,isLoading:!1,search:!1,title:null,view:null},mutations:{SET_BREADCRUMB:function(t,e){t.breadcrumb=e},SET_DIALOG:function(t,e){t.dialog=e},SET_DRAG:function(t,e){t.drag=e},SET_SEARCH:function(t,e){!0===e&&(e={}),t.search=e},SET_TITLE:function(t,e){t.title=e},SET_VIEW:function(t,e){t.view=e},START_LOADING:function(t){t.isLoading=!0},STOP_LOADING:function(t){t.isLoading=!1}},actions:{breadcrumb:function(t,e){t.commit("SET_BREADCRUMB",e)},dialog:function(t,e){t.commit("SET_DIALOG",e)},drag:function(t,e){t.commit("SET_DRAG",e)},isLoading:function(t,e){t.commit(!0===e?"START_LOADING":"STOP_LOADING")},search:function(t,e){t.commit("SET_SEARCH",e)},title:function(t,e){t.commit("SET_TITLE",e),document.title=e||"",t.state.system.info.title&&(document.title+=null!==e?" | "+t.state.system.info.title:t.state.system.info.title)},view:function(t,e){t.commit("SET_VIEW",e)}},modules:{content:Gm,heartbeat:Jm,languages:Zm,notification:Xm,system:Qm,translation:tg,user:og}}),lg={running:0,request:function(t,e){var n=this,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];e=Wi()(e||{},{credentials:"same-origin",cache:"no-store",headers:Object(I["a"])({"x-requested-with":"xmlhttprequest","content-type":"application/json"},e.headers)}),rg.state.languages.current&&(e.headers["x-language"]=rg.state.languages.current.code),e.headers["x-csrf"]=window.panel.csrf;var s=t+"/"+Hm()(e);return hg.config.onStart(s,i),this.running++,fetch(hg.config.endpoint+"/"+t,e).then(function(t){return t.text()}).then(function(t){try{return JSON.parse(t)}catch(e){throw new Error("The JSON response from the API could not be parsed. Please check your API connection.")}}).then(function(t){if(t.status&&"error"===t.status)throw t;var e=t;return t.data&&t.type&&"model"===t.type&&(e=t.data),n.running--,hg.config.onComplete(s),hg.config.onSuccess(t),e}).catch(function(t){throw n.running--,hg.config.onComplete(s),hg.config.onError(t),t})},get:function(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return e&&(t+="?"+kt()(e).map(function(t){var n=e[t];return void 0!==n&&null!==n?t+"="+n:null}).filter(function(t){return null!==t}).join("&")),this.request(t,Wi()(n||{},{method:"GET"}),i)},post:function(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"POST",s=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return this.request(t,Wi()(n||{},{method:i,body:Hm()(e)}),s)},patch:function(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return this.post(t,e,n,"PATCH",i)},delete:function(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return this.post(t,e,n,"DELETE",i)}},ug={list:function(t){return hg.get("roles",t)},get:function(t){return hg.get("roles/"+t)},options:function(t){return this.list(t).then(function(t){return t.data.map(function(t){return{info:t.description||"(".concat(z["a"].i18n.translate("role.description.placeholder"),")"),text:t.title,value:t.name}})})}},cg={info:function(t){return hg.get("system",t)},install:function(t){return hg.post("system/install",t).then(function(t){return t.user})},register:function(t){return hg.post("system/register",t)}},dg={get:function(t){return hg.get("site",t)},update:function(t){return hg.post("site",t)},title:function(t){return hg.patch("site/title",{title:t})},options:function(){return hg.get("site",{select:"options"}).then(function(t){var e=t.options,n=[];return n.push({click:"rename",icon:"title",text:z["a"].i18n.translate("rename"),disabled:!e.changeTitle}),n})},children:function(t){return hg.post("site/children/search",t)},blueprint:function(){return hg.get("site/blueprint")},blueprints:function(){return hg.get("site/blueprints")}},pg={list:function(){return hg.get("translations")},get:function(t){return hg.get("translations/"+t)},options:function(){var t=[];return this.list().then(function(e){return t=e.data.map(function(t){return{value:t.id,text:t.name}}),t})}},fg={create:function(t){return hg.post(this.url(),t)},list:function(t){return hg.post(this.url(null,"search"),t)},get:function(t,e){return hg.get(this.url(t),e)},update:function(t,e){return hg.patch(this.url(t),e)},delete:function(t){return hg.delete(this.url(t))},changeEmail:function(t,e){return hg.patch(this.url(t,"email"),{email:e})},changeLanguage:function(t,e){return hg.patch(this.url(t,"language"),{language:e})},changeName:function(t,e){return hg.patch(this.url(t,"name"),{name:e})},changePassword:function(t,e){return hg.patch(this.url(t,"password"),{password:e})},changeRole:function(t,e){return hg.patch(this.url(t,"role"),{role:e})},deleteAvatar:function(t){return hg.delete(this.url(t,"avatar"))},blueprint:function(t){return hg.get(this.url(t,"blueprint"))},breadcrumb:function(t){return[{link:"/users/"+t.id,label:t.username}]},options:function(t){return hg.get(this.url(t),{select:"options"}).then(function(t){var e=t.options,n=[];return n.push({click:"rename",icon:"title",text:z["a"].i18n.translate("user.changeName"),disabled:!e.changeName}),n.push({click:"email",icon:"email",text:z["a"].i18n.translate("user.changeEmail"),disabled:!e.changeEmail}),n.push({click:"role",icon:"bolt",text:z["a"].i18n.translate("user.changeRole"),disabled:!e.changeRole}),n.push({click:"password",icon:"key",text:z["a"].i18n.translate("user.changePassword"),disabled:!e.changePassword}),n.push({click:"language",icon:"globe",text:z["a"].i18n.translate("user.changeLanguage"),disabled:!e.changeLanguage}),n.push({click:"remove",icon:"trash",text:z["a"].i18n.translate("user.delete"),disabled:!e.delete}),n})},url:function(t,e){var n=t?"users/"+t:"users";return e&&(n+="/"+e),n},link:function(t,e){return"/"+this.url(t,e)}},hg=Object(I["a"])({config:{onStart:function(){},onComplete:function(){},onSuccess:function(){},onError:function(t){throw window.console.log(t.message),t}},auth:Mm,files:zm,pages:Um,roles:ug,system:cg,site:dg,translations:pg,users:fg},lg);hg.config.endpoint=A.api,hg.requests=[],hg.config.onStart=function(t,e){!1===e&&rg.dispatch("isLoading",!0),hg.requests.push(t)},hg.config.onComplete=function(t){hg.requests=hg.requests.filter(function(e){return e!==t}),0===hg.requests.length&&rg.dispatch("isLoading",!1)},hg.config.onError=function(t){A.debug&&window.console.error(t),403!==t.code||"Unauthenticated"!==t.message&&"access.panel"!==t.key||rg.dispatch("user/logout",!0)};var mg=setInterval(hg.auth.user,3e5);hg.config.onSuccess=function(){clearInterval(mg),mg=setInterval(hg.auth.user,3e5)},z["a"].prototype.$api=hg,z["a"].config.errorHandler=function(t){A.debug&&window.console.error(t),rg.dispatch("notification/error",{message:t.message||"An error occurred. Please reload the panel"})},window.panel=window.panel||{},window.panel.error=function(t,e){A.debug&&window.console.error(t+": "+e),rg.dispatch("error",t+". See the console for more information.")},RegExp.escape=function(t){return t.replace(/[Lp\{\}]|[\$\(-\+\x2D-\/\?\[-\^\{-\}]+/,"\\$&")};var gg=function(t,e){t=String(t);var n="";e=(e||2)-t.length;while(n.length0&&void 0!==arguments[0]?arguments[0]:"3/2",e=String(t).split("/");if(2!==e.length)return"100%";var n=Number(e[0]),i=Number(e[1]),s=100;return 0!==n&&0!==i&&(s=100/n*i),s+"%"},vg=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",i="-";return n="a-z0-9"+n,t=t.trim().toLowerCase(),e.forEach(function(e){e&&kt()(e).forEach(function(n){var i="/"!==n.substr(0,1),s=n.substring(1,n.length-1),a=i?n:s;t=t.replace(new RegExp(RegExp.escape(a),"g"),e[n])})}),t=t.replace("/[^\t\n\r -~]/",""),t=t.replace(new RegExp("[^"+n+"]","ig"),i),t=t.replace(new RegExp("["+RegExp.escape(i)+"]{2,}","g"),i),t=t.replace("/",i),t=t.replace(new RegExp("^[^"+n+"]+","g"),""),t=t.replace(new RegExp("[^"+n+"]+$","g"),""),t},kg=function(t){t=t||{};var e=t.desc?-1:1,n=-e,i=/^0/,s=/\s+/g,a=/^\s+|\s+$/g,o=/[^\x00-\x80]/,r=/^0x[0-9a-f]+$/i,l=/(0x[\da-fA-F]+|(^[\+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|\d+)/g,u=/(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,c=t.insensitive?function(t){return d(""+t).replace(a,"")}:function(t){return(""+t).replace(a,"")};function d(t){return t.toLocaleLowerCase?t.toLocaleLowerCase():t.toLowerCase()}function p(t){return t.replace(l,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0")}function f(t,e){return(!t.match(i)||1===e)&&Ks()(t)||t.replace(s," ").replace(a,"")||0}return function(t,i){var s=c(t),a=c(i);if(!s&&!a)return 0;if(!s&&a)return n;if(s&&!a)return e;var l=p(s),d=p(a),h=ms()(s.match(r),16)||1!==l.length&&Date.parse(s),m=ms()(a.match(r),16)||h&&a.match(u)&&Date.parse(a)||null;if(m){if(hm)return e}for(var g=l.length,b=d.length,v=0,k=Math.max(g,b);v0)return e;if(y<0)return n;if(v===k-1)return 0}else{if($<_)return n;if($>_)return e}}return 0}},$g={ucfirst:function(t){var e=String(t);return e.charAt(0).toUpperCase()+e.substr(1)},lcfirst:function(t){var e=String(t);return e.charAt(0).toLowerCase()+e.substr(1)}},_g=function(t,e){var n={url:"/",field:"file",method:"POST",accept:"text",attributes:{},complete:function(){},error:function(){},success:function(){},progress:function(){}},i=Wi()(n,e),s=new FormData;s.append(i.field,t,t.name),i.attributes&&kt()(i.attributes).forEach(function(t){s.append(t,i.attributes[t])});var a=new XMLHttpRequest,o=function(e){if(e.lengthComputable&&i.progress){var n=Math.max(0,Math.min(100,e.loaded/e.total*100));i.progress(a,t,Math.ceil(n))}};a.addEventListener("loadstart",o),a.addEventListener("progress",o),a.addEventListener("load",function(e){var n=null;try{n=JSON.parse(e.target.response)}catch(s){n={status:"error",message:"The file could not be uploaded"}}n.status&&"error"===n.status?i.error(a,t,n):(i.success(a,t,n),i.progress(a,t,100))}),a.addEventListener("error",function(e){var n=JSON.parse(e.target.response);i.error(a,t,n),i.progress(a,t,100)}),a.open("POST",i.url,!0),i.headers&&kt()(i.headers).forEach(function(t){var e=i.headers[t];a.setRequestHeader(t,e)}),a.send(s)},yg=function(t){return!!t.dataTransfer&&(!!t.dataTransfer.types&&(!0===t.dataTransfer.types.includes("Files")&&!1===t.dataTransfer.types.includes("text/plain")))};z["a"].prototype.$helper={clone:Ym,isUploadEvent:yg,debounce:wt,pad:gg,ratio:bg,slug:vg,sort:kg,string:$g,upload:_g};var xg=n("f2f3");z["a"].use(xg["a"].plugin,rg);var wg=n("19e9"),Og=n.n(wg),Cg=n("5a0c"),Sg=n.n(Cg),Eg=n("f906"),jg=n.n(Eg);Sg.a.extend(jg.a),z["a"].prototype.$library={autosize:Og.a,dayjs:Sg.a};var Tg=n("2d1f"),Ig=n.n(Tg),Lg={};for(var qg in z["a"].options.components)Lg[qg]=z["a"].options.components[qg];var Ag=function(t,e){e.template||e.render||e.extends?(e.extends&&"string"===typeof e.extends&&(e.extends=Lg[e.extends],e.template&&(e.render=null)),e.mixins&&(e.mixins=e.mixins.map(function(t){return"string"===typeof t?Lg[t]:t})),Lg[t]&&window.console.warn('Plugin is replacing "'.concat(t,'"')),z["a"].component(t,e)):rg.dispatch("notification/error",'Neither template or render method provided nor extending a component when loading plugin component "'.concat(t,'". The component has not been registered.'))};Ig()(window.panel.plugins.components).forEach(function(t){var e=Object(Vm["a"])(t,2),n=e[0],i=e[1];Ag(n,i)}),Ig()(window.panel.plugins.fields).forEach(function(t){var e=Object(Vm["a"])(t,2),n=e[0],i=e[1];Ag(n,i)}),Ig()(window.panel.plugins.sections).forEach(function(t){var e=Object(Vm["a"])(t,2),n=e[0],i=e[1];Ag(n,Object(I["a"])({},i,{mixins:[Zf].concat(i.mixins||[])}))}),Ig()(window.panel.plugins.views).forEach(function(t){var e=Object(Vm["a"])(t,2),n=e[0],i=e[1];if(!i.component)return rg.dispatch("notification/error",'No view component provided when loading view "'.concat(n,'". The view has not been registered.')),void delete window.panel.plugins.views[n];i.link="/plugins/"+n,void 0===i.icon&&(i.icon="page"),void 0===i.menu&&(i.menu=!0),window.panel.plugins.views[n]={link:i.link,icon:i.icon,menu:i.menu},z["a"].component("k-"+n+"-plugin-view",i.component)}),window.panel.plugins.use.forEach(function(t){z["a"].use(t)}),z["a"].config.productionTip=!1,z["a"].config.devtools=!0,z["a"].use(M),z["a"].use(R),z["a"].use(F.a),new z["a"]({router:ag,store:rg,created:function(){var t=this;window.panel.app=this,window.panel.plugins.created.forEach(function(e){e(t)}),this.$store.dispatch("content/init")},render:function(t){return t(D)}}).$mount("#app")},5714:function(t,e,n){},"580a":function(t,e,n){"use strict";var i=n("61ab"),s=n.n(i);s.a},"589a":function(t,e,n){},"58e5":function(t,e,n){},"5ab5":function(t,e,n){},"5aee":function(t,e,n){"use strict";var i=n("04b2"),s=n.n(i);s.a},"5b23":function(t,e,n){"use strict";var i=n("9798"),s=n.n(i);s.a},"5c0b":function(t,e,n){"use strict";var i=n("5e27"),s=n.n(i);s.a},"5d33":function(t,e,n){"use strict";var i=n("2246"),s=n.n(i);s.a},"5e27":function(t,e,n){},"5f12":function(t,e,n){},6018:function(t,e,n){"use strict";var i=n("e30b"),s=n.n(i);s.a},"61ab":function(t,e,n){},"64e4":function(t,e,n){"use strict";var i=n("1340"),s=n.n(i);s.a},"64e6":function(t,e,n){},"65a9":function(t,e,n){},"696b5":function(t,e,n){"use strict";var i=n("0cdc"),s=n.n(i);s.a},"6a18":function(t,e,n){"use strict";var i=n("de8a"),s=n.n(i);s.a},"6ab3":function(t,e,n){"use strict";var i=n("784e"),s=n.n(i);s.a},"6ab9":function(t,e,n){},"6b7f":function(t,e,n){},"6bcd":function(t,e,n){"use strict";var i=n("9e0a"),s=n.n(i);s.a},"6e56":function(t,e,n){},"6f7b":function(t,e,n){"use strict";var i=n("5ab5"),s=n.n(i);s.a},7075:function(t,e,n){},"718c":function(t,e,n){"use strict";var i=n("773d"),s=n.n(i);s.a},7568:function(t,e,n){"use strict";var i=n("4150"),s=n.n(i);s.a},"75cd":function(t,e,n){},7737:function(t,e,n){"use strict";var i=n("ca19"),s=n.n(i);s.a},"773d":function(t,e,n){},"778b":function(t,e,n){},7797:function(t,e,n){},"784e":function(t,e,n){},"7a7d":function(t,e,n){"use strict";var i=n("65a9"),s=n.n(i);s.a},"7d2d":function(t,e,n){},"7d5d":function(t,e,n){"use strict";var i=n("6ab9"),s=n.n(i);s.a},"7dc7":function(t,e,n){"use strict";var i=n("eb17"),s=n.n(i);s.a},"7e0c":function(t,e,n){},"7e85":function(t,e,n){"use strict";var i=n("d1c5"),s=n.n(i);s.a},"7f6e":function(t,e,n){"use strict";var i=n("4364"),s=n.n(i);s.a},"862b":function(t,e,n){"use strict";var i=n("589a"),s=n.n(i);s.a},"893d":function(t,e,n){"use strict";var i=n("abb3"),s=n.n(i);s.a},"8ae6":function(t,e,n){},"8c28":function(t,e,n){"use strict";var i=n("3d5b"),s=n.n(i);s.a},"8e4d":function(t,e,n){},"910b":function(t,e,n){},"957b":function(t,e,n){},9749:function(t,e,n){},"977f":function(t,e,n){"use strict";var i=n("b7f5"),s=n.n(i);s.a},9798:function(t,e,n){},9799:function(t,e,n){"use strict";var i=n("4fe0"),s=n.n(i);s.a},9811:function(t,e,n){},"98a1":function(t,e,n){"use strict";var i=n("f0cb"),s=n.n(i);s.a},"9bd5":function(t,e,n){"use strict";var i=n("64e6"),s=n.n(i);s.a},"9df7":function(t,e,n){},"9e0a":function(t,e,n){},"9e26":function(t,e,n){"use strict";var i=n("a440"),s=n.n(i);s.a},a134:function(t,e,n){"use strict";var i=n("4390"),s=n.n(i);s.a},a440:function(t,e,n){},a567:function(t,e,n){"use strict";var i=n("c0b5"),s=n.n(i);s.a},a5f3:function(t,e,n){"use strict";var i=n("43f4"),s=n.n(i);s.a},a66d:function(t,e,n){"use strict";var i=n("2eb5"),s=n.n(i);s.a},a79d:function(t,e,n){},abb3:function(t,e,n){},ac27:function(t,e,n){"use strict";var i=n("3c9d"),s=n.n(i);s.a},b0d6:function(t,e,n){"use strict";var i=n("d31d"),s=n.n(i);s.a},b37e:function(t,e,n){},b3c3:function(t,e,n){},b5d2:function(t,e,n){"use strict";var i=n("ed7b"),s=n.n(i);s.a},b746:function(t,e,n){"use strict";var i=n("7e0c"),s=n.n(i);s.a},b7f5:function(t,e,n){},ba8f:function(t,e,n){"use strict";var i=n("9749"),s=n.n(i);s.a},bb41:function(t,e,n){"use strict";var i=n("ceb4"),s=n.n(i);s.a},bd96:function(t,e,n){"use strict";var i=n("d6a4"),s=n.n(i);s.a},bf53:function(t,e,n){"use strict";var i=n("3c80"),s=n.n(i);s.a},c0b5:function(t,e,n){},c119:function(t,e,n){"use strict";var i=n("4b49"),s=n.n(i);s.a},c7c8:function(t,e,n){"use strict";var i=n("1be2"),s=n.n(i);s.a},c857:function(t,e,n){"use strict";var i=n("7d2d"),s=n.n(i);s.a},c9cb:function(t,e,n){"use strict";var i=n("b37e"),s=n.n(i);s.a},ca19:function(t,e,n){},ca3a:function(t,e,n){},cb8f:function(t,e,n){"use strict";var i=n("8e4d"),s=n.n(i);s.a},cc79:function(t,e,n){"use strict";var i=n("a79d"),s=n.n(i);s.a},cca8:function(t,e,n){"use strict";var i=n("18b7"),s=n.n(i);s.a},ceb4:function(t,e,n){},d0c1:function(t,e,n){"use strict";var i=n("9df7"),s=n.n(i);s.a},d0e7:function(t,e,n){},d1c5:function(t,e,n){},d221:function(t,e,n){"use strict";var i=n("6b7f"),s=n.n(i);s.a},d31d:function(t,e,n){},d6a4:function(t,e,n){},d6c1:function(t,e,n){},d6fc:function(t,e,n){"use strict";var i=n("08ec"),s=n.n(i);s.a},d9c4:function(t,e,n){},daa8:function(t,e,n){"use strict";var i=n("e60b"),s=n.n(i);s.a},db92:function(t,e,n){},ddfd:function(t,e,n){"use strict";var i=n("4dc8"),s=n.n(i);s.a},de8a:function(t,e,n){},df0d:function(t,e,n){"use strict";var i=n("3ab9"),s=n.n(i);s.a},e30b:function(t,e,n){},e60b:function(t,e,n){},e697:function(t,e,n){},eb17:function(t,e,n){},ec72:function(t,e,n){},ed7b:function(t,e,n){},ee15:function(t,e,n){"use strict";var i=n("fd81"),s=n.n(i);s.a},f0cb:function(t,e,n){},f56d:function(t,e,n){"use strict";var i=n("75cd"),s=n.n(i);s.a},f5e3:function(t,e,n){},f8a7:function(t,e,n){"use strict";var i=n("db92"),s=n.n(i);s.a},f95f:function(t,e,n){"use strict";var i=n("5f12"),s=n.n(i);s.a},fa6a:function(t,e,n){"use strict";var i=n("778b"),s=n.n(i);s.a},fb1a:function(t,e,n){},fc0f:function(t,e,n){"use strict";var i=n("424a"),s=n.n(i);s.a},fd81:function(t,e,n){},ff6d:function(t,e,n){},fffc:function(t,e,n){}});
\ No newline at end of file
diff --git a/panel/public/img/icons.svg b/panel/public/img/icons.svg
index 87ef6686c5..090d7abb23 100644
--- a/panel/public/img/icons.svg
+++ b/panel/public/img/icons.svg
@@ -30,12 +30,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -44,10 +64,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -65,6 +115,10 @@
+
+
+
+
@@ -159,6 +213,9 @@
+
+
+
@@ -168,6 +225,13 @@
+
+
+
+
+
+
+
@@ -186,6 +250,14 @@
+
+
+
+
+
+
+
+
@@ -198,13 +270,13 @@
-
-
-
+
+
+
@@ -219,6 +291,9 @@
+
+
+
@@ -229,18 +304,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -248,9 +339,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -272,9 +375,16 @@
+
+
+
+
+
+
+
@@ -292,49 +402,23 @@
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/panel/public/index.html b/panel/public/index.html
index e78041caac..9c1c9a5bfc 100644
--- a/panel/public/index.html
+++ b/panel/public/index.html
@@ -18,15 +18,18 @@
-
+
-
+
-
+
@@ -41,55 +44,131 @@
-
+
-
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
+
+
+
+
-
+
-
+
@@ -100,16 +179,19 @@
-
+
-
+
-
+
@@ -123,13 +205,16 @@
-
-
+
+
-
+
@@ -143,7 +228,8 @@
-
+
@@ -173,17 +259,33 @@
-
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
@@ -193,79 +295,148 @@
-
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
-
-
-
+
-
+
+
+
+
-
+
-
+
+
+
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
-
+
-
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
@@ -276,81 +447,78 @@
-
+
-
+
-
+
-
+
+
+
+
+
-
+
+
+
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/panel/src/App.vue b/panel/src/App.vue
index ac19e15f23..51cc218f54 100644
--- a/panel/src/App.vue
+++ b/panel/src/App.vue
@@ -101,6 +101,43 @@ export default {
box-sizing: border-box;
}
+:root {
+ /** Colors **/
+ --color-backdrop: #{$color-backdrop};
+ --color-background: #{$color-background};
+ --color-border: #{$color-border};
+ --color-focus: #{$color-focus};
+ --color-focus-light: #{$color-focus-on-dark};
+ --color-focus-outline: #{$color-focus-outline};
+ --color-negative: #{$color-negative};
+ --color-negative-light: #{$color-negative-on-dark};
+ --color-negative-outline: #{$color-negative-outline};
+ --color-notice: #{$color-notice};
+ --color-notice-light: #{$color-notice-on-dark};
+ --color-positive: #{$color-positive};
+ --color-positive-light: #{$color-positive-on-dark};
+ --color-positive-outline: #{$color-positive-outline};
+ --color-text: #{$color-dark};
+ --color-text-light: #{$color-dark-grey};
+
+ /** Font families **/
+ --font-family-mono: #{$font-family-mono};
+ --font-family-sans: #{$font-family-sans};
+
+ /** Font sizes **/
+ --font-size-tiny: #{$font-size-tiny};
+ --font-size-small: #{$font-size-small};
+ --font-size-medium: #{$font-size-medium};
+ --font-size-large: #{$font-size-large};
+ --font-size-huge: #{$font-size-huge};
+ --font-size-monster: #{$font-size-monster};
+
+ /** Shadows **/
+ --box-shadow-dropdown: #{$box-shadow};
+ --box-shadow-item: #{$box-shadow-card};
+ --box-shadow-focus: #{$box-shadow-focus-full};
+}
+
noscript {
padding: 1.5rem;
display: flex;
diff --git a/panel/src/components/Dialogs/Dialog.vue b/panel/src/components/Dialogs/Dialog.vue
index 7f0a6a644f..0f1babb673 100644
--- a/panel/src/components/Dialogs/Dialog.vue
+++ b/panel/src/components/Dialogs/Dialog.vue
@@ -153,120 +153,140 @@
diff --git a/panel/src/components/Dialogs/FileRemoveDialog.vue b/panel/src/components/Dialogs/FileRemoveDialog.vue
index 0d4d96addb..de3d2cd606 100644
--- a/panel/src/components/Dialogs/FileRemoveDialog.vue
+++ b/panel/src/components/Dialogs/FileRemoveDialog.vue
@@ -40,7 +40,7 @@ export default {
.delete(this.parent, this.filename)
.then(() => {
// remove data from cache
- this.$store.dispatch("form/remove", "files/" + this.id);
+ this.$store.dispatch("content/remove", "files/" + this.id);
this.$store.dispatch("notification/success", ":)");
this.$events.$emit("file.delete", this.id);
this.$emit("success");
diff --git a/panel/src/components/Dialogs/FileRenameDialog.vue b/panel/src/components/Dialogs/FileRenameDialog.vue
index f681aac943..8eb7ee79f6 100644
--- a/panel/src/components/Dialogs/FileRenameDialog.vue
+++ b/panel/src/components/Dialogs/FileRenameDialog.vue
@@ -18,7 +18,6 @@
@@ -122,11 +146,6 @@ export default {
flex-grow: 1;
text-align: center;
}
-
-.k-pages-dialog-search {
- margin-bottom: 0.5rem;
-}
-
.k-pages-dialog .k-list-item {
cursor: pointer;
}
diff --git a/panel/src/components/Dialogs/SiteRenameDialog.vue b/panel/src/components/Dialogs/SiteRenameDialog.vue
index 599bcefb50..6bfb944fd9 100644
--- a/panel/src/components/Dialogs/SiteRenameDialog.vue
+++ b/panel/src/components/Dialogs/SiteRenameDialog.vue
@@ -16,6 +16,14 @@ export default {
});
},
submit() {
+ // prevent empty title with just spaces
+ this.page.title = this.page.title.trim();
+
+ if (this.page.title.length === 0) {
+ this.$refs.dialog.error(this.$t("error.site.changeTitle.empty"));
+ return;
+ }
+
this.$api.site
.title(this.page.title)
.then(() => {
diff --git a/panel/src/components/Dialogs/UserEmailDialog.vue b/panel/src/components/Dialogs/UserEmailDialog.vue
index 204399eb87..e789af8732 100644
--- a/panel/src/components/Dialogs/UserEmailDialog.vue
+++ b/panel/src/components/Dialogs/UserEmailDialog.vue
@@ -57,7 +57,7 @@ export default {
.then(response => {
// remove changes for the old user
- this.$store.dispatch("form/revert", "users/" + this.user.id);
+ this.$store.dispatch("content/revert", "users/" + this.user.id);
// If current panel user, update store
if (this.$user.id === this.user.id) {
diff --git a/panel/src/components/Dialogs/UserPasswordDialog.vue b/panel/src/components/Dialogs/UserPasswordDialog.vue
index 4999310384..92822078dc 100644
--- a/panel/src/components/Dialogs/UserPasswordDialog.vue
+++ b/panel/src/components/Dialogs/UserPasswordDialog.vue
@@ -57,7 +57,7 @@ export default {
});
},
submit() {
- if (this.values.password.length < 8) {
+ if (!this.values.password || this.values.password.length < 8) {
this.$refs.dialog.error(this.$t("error.user.password.invalid"));
return false;
}
diff --git a/panel/src/components/Dialogs/UserRemoveDialog.vue b/panel/src/components/Dialogs/UserRemoveDialog.vue
index 61f1537573..9fa4a1717f 100644
--- a/panel/src/components/Dialogs/UserRemoveDialog.vue
+++ b/panel/src/components/Dialogs/UserRemoveDialog.vue
@@ -39,7 +39,7 @@ export default {
.then(() => {
// remove data from cache
- this.$store.dispatch("form/remove", "users/" + this.user.id);
+ this.$store.dispatch("content/remove", "users/" + this.user.id);
this.success({
message: ":)",
diff --git a/panel/src/components/Dialogs/UsersDialog.vue b/panel/src/components/Dialogs/UsersDialog.vue
index 49d32f5130..20dac3743f 100644
--- a/panel/src/components/Dialogs/UsersDialog.vue
+++ b/panel/src/components/Dialogs/UsersDialog.vue
@@ -12,33 +12,53 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
{{ $t("dialog.users.empty") }}
diff --git a/panel/src/components/Forms/Autocomplete.vue b/panel/src/components/Forms/Autocomplete.vue
index dc474e4a9e..9dc28f74a1 100644
--- a/panel/src/components/Forms/Autocomplete.vue
+++ b/panel/src/components/Forms/Autocomplete.vue
@@ -21,7 +21,6 @@
diff --git a/panel/src/components/Forms/Field/PagesField.vue b/panel/src/components/Forms/Field/PagesField.vue
index ded817d0d6..47cd4d5efb 100644
--- a/panel/src/components/Forms/Field/PagesField.vue
+++ b/panel/src/components/Forms/Field/PagesField.vue
@@ -16,6 +16,7 @@
:handle="true"
:list="selected"
:data-size="size"
+ :data-invalid="isInvalid"
@end="onInput"
>
@@ -65,6 +67,7 @@ export default {
endpoint: this.endpoints.field,
max: this.max,
multiple: this.multiple,
+ search: this.search,
selected: this.selected.map(page => page.id),
});
}
diff --git a/panel/src/components/Forms/Field/StructureField.vue b/panel/src/components/Forms/Field/StructureField.vue
index a970353821..2e7f6ef887 100644
--- a/panel/src/components/Forms/Field/StructureField.vue
+++ b/panel/src/components/Forms/Field/StructureField.vue
@@ -44,13 +44,22 @@
-
+
{{ empty || $t("field.structure.empty") }}
-
+
#
@@ -99,6 +108,7 @@
:value="item[columnName]"
:column="column"
:field="fields[columnName]"
+ @input="update(index, columnName, $event)"
/>
@@ -131,12 +141,8 @@
-
diff --git a/panel/src/components/Forms/Previews/ToggleFieldPreview.vue b/panel/src/components/Forms/Previews/ToggleFieldPreview.vue
new file mode 100644
index 0000000000..5949993dc6
--- /dev/null
+++ b/panel/src/components/Forms/Previews/ToggleFieldPreview.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
diff --git a/panel/src/components/Forms/Upload.vue b/panel/src/components/Forms/Upload.vue
index 90709fb609..2154f3391c 100644
--- a/panel/src/components/Forms/Upload.vue
+++ b/panel/src/components/Forms/Upload.vue
@@ -46,8 +46,6 @@
+
+
diff --git a/panel/src/components/Navigation/ButtonLink.vue b/panel/src/components/Navigation/ButtonLink.vue
new file mode 100644
index 0000000000..ff0658142d
--- /dev/null
+++ b/panel/src/components/Navigation/ButtonLink.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
diff --git a/panel/src/components/Navigation/ButtonNative.vue b/panel/src/components/Navigation/ButtonNative.vue
new file mode 100644
index 0000000000..b687e96e9f
--- /dev/null
+++ b/panel/src/components/Navigation/ButtonNative.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
diff --git a/panel/src/components/Navigation/DropdownContent.vue b/panel/src/components/Navigation/DropdownContent.vue
index 48209f9449..06f53947a0 100644
--- a/panel/src/components/Navigation/DropdownContent.vue
+++ b/panel/src/components/Navigation/DropdownContent.vue
@@ -97,46 +97,65 @@ export default {
break;
case "ArrowUp":
e.preventDefault();
-
+
while (true) {
this.current--;
-
+
if (this.current < 0) {
this.close();
this.$emit("leave", e.code);
break;
}
-
+
if (
- this.$children[this.current] &&
+ this.$children[this.current] &&
this.$children[this.current].disabled === false
) {
this.focus(this.current);
break;
}
}
-
+
break;
case "ArrowDown":
e.preventDefault();
-
+
while (true) {
this.current++;
-
+
if (this.current > this.$children.length - 1) {
const enabled = this.$children.filter(x => x.disabled === false);
this.current = this.$children.indexOf(enabled[enabled.length - 1]);
break;
}
-
+
if (
- this.$children[this.current] &&
+ this.$children[this.current] &&
this.$children[this.current].disabled === false
) {
this.focus(this.current);
break;
}
}
+
+ break;
+ case "Tab":
+ while (true) {
+ this.current++;
+
+ if (this.current > this.$children.length - 1) {
+ this.close();
+ this.$emit("leave", e.code);
+ break;
+ }
+
+ if (
+ this.$children[this.current] &&
+ this.$children[this.current].disabled === false
+ ) {
+ break;
+ }
+ }
break;
}
@@ -155,6 +174,7 @@ export default {
box-shadow: $box-shadow;
border-radius: $border-radius;
text-align: left;
+ margin-bottom: 6rem;
[dir="ltr"] & {
left: 0;
diff --git a/panel/src/components/Navigation/Link.vue b/panel/src/components/Navigation/Link.vue
index 11577a564b..42341f08ab 100644
--- a/panel/src/components/Navigation/Link.vue
+++ b/panel/src/components/Navigation/Link.vue
@@ -23,7 +23,10 @@
+
+
diff --git a/panel/src/components/Navigation/Pagination.vue b/panel/src/components/Navigation/Pagination.vue
index 0f1b0fa046..2163406551 100644
--- a/panel/src/components/Navigation/Pagination.vue
+++ b/panel/src/components/Navigation/Pagination.vue
@@ -20,19 +20,21 @@
class="k-pagination-selector"
@open="$nextTick(() => $refs.page.focus())"
>
-
-
-
-
+
+
+
@@ -93,7 +95,9 @@ export default {
},
pageLabel: {
type: String,
- default: "Page"
+ default() {
+ return this.$t("pagination.page");
+ }
},
prevLabel: {
type: String,
@@ -154,7 +158,7 @@ export default {
},
watch: {
page(page) {
- this.currentPage = page;
+ this.currentPage = parseInt(page);
}
},
created() {
@@ -184,7 +188,7 @@ export default {
}
this.$emit("paginate", {
- page: parseInt(this.currentPage),
+ page: this.currentPage,
start: this.start,
end: this.end,
limit: this.limit,
@@ -240,8 +244,7 @@ export default {
position: absolute;
top: 100%;
left: 50%;
- width: 14rem;
- margin-left: -7rem;
+ transform: translateX(-50%);
background: $color-black;
[dir="ltr"] & {
@@ -252,30 +255,23 @@ export default {
direction: rtl;
}
}
-.k-pagination-selector > div {
- font-size: $font-size-small;
+
+.k-pagination-settings {
display: flex;
align-items: center;
+ justify-content: space-between;
}
-.k-pagination-selector .k-button {
- padding: .75rem 1rem;
+.k-pagination-settings .k-button {
line-height: 1;
}
-.k-pagination-selector > div > label {
- padding: .75rem 1rem;
-}
-.k-pagination-selector > div > input {
- flex-grow: 1;
- font: inherit;
- border: 0;
- padding: .75rem 1rem;
- color: #fff;
- background: none;
- text-align: center;
- border-left: 1px solid rgba(#fff, .2);
- border-right: 1px solid rgba(#fff, .2);
+.k-pagination-settings label {
+ display: flex;
+ border-right: 1px solid rgba(#fff, .35);
+ align-items: center;
+ padding: .625rem 1rem;
+ font-size: $font-size-tiny;
}
-.k-pagination-selector > div > input:focus {
- outline: 0;
+.k-pagination-settings label span {
+ margin-right: .5rem;
}
diff --git a/panel/src/components/Navigation/Search.vue b/panel/src/components/Navigation/Search.vue
index 75de0adc13..f460600c98 100644
--- a/panel/src/components/Navigation/Search.vue
+++ b/panel/src/components/Navigation/Search.vue
@@ -52,9 +52,8 @@
diff --git a/panel/src/components/Views/PageView.vue b/panel/src/components/Views/PageView.vue
index e01d00d2cf..2049031a12 100644
--- a/panel/src/components/Views/PageView.vue
+++ b/panel/src/components/Views/PageView.vue
@@ -27,6 +27,7 @@
:disabled="!permissions.changeStatus || isLocked"
:icon="!permissions.changeStatus || isLocked ? 'protected' : 'circle'"
:responsive="true"
+ :tooltip="status.label"
@click="action('status')"
>
{{ status.label }}
@@ -198,7 +199,7 @@ export default {
this.$store.dispatch("breadcrumb", this.$api.pages.breadcrumb(page));
this.$store.dispatch("title", this.page.title);
- this.$store.dispatch("form/create", {
+ this.$store.dispatch("content/create", {
id: "pages/" + this.page.id,
api: this.$api.pages.link(this.page.id),
content: this.page.content
diff --git a/panel/src/components/Views/SettingsView.vue b/panel/src/components/Views/SettingsView.vue
index 6eb6821ed7..e5a1fa0e8b 100644
--- a/panel/src/components/Views/SettingsView.vue
+++ b/panel/src/components/Views/SettingsView.vue
@@ -92,7 +92,7 @@ export default {
}
},
created() {
- this.$store.dispatch("form/current", null);
+ this.$store.dispatch("content/current", null);
this.$store.dispatch("title", this.$t("view.settings"));
this.$store.dispatch("breadcrumb", []);
this.fetch();
diff --git a/panel/src/components/Views/SiteView.vue b/panel/src/components/Views/SiteView.vue
index dffe176772..911b8b7007 100644
--- a/panel/src/components/Views/SiteView.vue
+++ b/panel/src/components/Views/SiteView.vue
@@ -61,7 +61,7 @@ export default {
},
computed: {
isLocked() {
- return this.$store.getters["form/lock"] !== null;
+ return this.$store.state.content.status.lock !== null;
},
language() {
return this.$store.state.languages.current;
@@ -90,7 +90,7 @@ export default {
};
this.$store.dispatch("breadcrumb", []);
this.$store.dispatch("title", null);
- this.$store.dispatch("form/create", {
+ this.$store.dispatch("content/create", {
id: "site",
api: "site",
content: site.content
diff --git a/panel/src/components/Views/UserView.vue b/panel/src/components/Views/UserView.vue
index 583f9eba9b..ab9582fbb7 100644
--- a/panel/src/components/Views/UserView.vue
+++ b/panel/src/components/Views/UserView.vue
@@ -237,7 +237,7 @@ export default {
}
this.$store.dispatch("title", this.user.name || this.user.email);
- this.$store.dispatch("form/create", {
+ this.$store.dispatch("content/create", {
id: "users/" + user.id,
api: this.$api.users.link(user.id),
content: user.content
diff --git a/panel/src/components/Views/UsersView.vue b/panel/src/components/Views/UsersView.vue
index 5b3628e61a..67ecfa67a3 100644
--- a/panel/src/components/Views/UsersView.vue
+++ b/panel/src/components/Views/UsersView.vue
@@ -95,7 +95,7 @@ export default {
}
},
created() {
- this.$store.dispatch("form/current", null);
+ this.$store.dispatch("content/current", null);
this.$api.roles.options().then(roles => {
this.roles = roles;
this.fetch();
diff --git a/panel/src/config/components.js b/panel/src/config/components.js
index 398d9f0ccd..da370320f6 100644
--- a/panel/src/config/components.js
+++ b/panel/src/config/components.js
@@ -1,5 +1,8 @@
import Vue from "vue";
+/* Style-only components */
+import "@/components/Misc/Invalid.vue";
+
/* Dialogs */
import Dialog from "@/components/Dialogs/Dialog.vue";
import ErrorDialog from "@/components/Dialogs/ErrorDialog.vue";
@@ -119,6 +122,7 @@ import ToolbarLinkDialog from "@/components/Forms/Toolbar/LinkDialog.vue";
import FilesFieldPreview from "@/components/Forms/Previews/FilesFieldPreview.vue";
import EmailFieldPreview from "@/components/Forms/Previews/EmailFieldPreview.vue";
import PagesFieldPreview from "@/components/Forms/Previews/PagesFieldPreview.vue";
+import ToggleFieldPreview from "@/components/Forms/Previews/ToggleFieldPreview.vue";
import UrlFieldPreview from "@/components/Forms/Previews/UrlFieldPreview.vue";
import UsersFieldPreview from "@/components/Forms/Previews/UsersFieldPreview.vue";
@@ -183,6 +187,7 @@ Vue.component("k-toolbar-link-dialog", ToolbarLinkDialog);
Vue.component("k-email-field-preview", EmailFieldPreview);
Vue.component("k-files-field-preview", FilesFieldPreview);
Vue.component("k-pages-field-preview", PagesFieldPreview);
+Vue.component("k-toggle-field-preview", ToggleFieldPreview);
Vue.component("k-url-field-preview", UrlFieldPreview);
Vue.component("k-users-field-preview", UsersFieldPreview);
@@ -240,7 +245,10 @@ Vue.component("k-text", Text);
/* Navigation */
import Button from "@/components/Navigation/Button.vue";
+import ButtonDisabled from "@/components/Navigation/ButtonDisabled.vue";
import ButtonGroup from "@/components/Navigation/ButtonGroup.vue";
+import ButtonLink from "@/components/Navigation/ButtonLink.vue";
+import ButtonNative from "@/components/Navigation/ButtonNative.vue";
import Dropdown from "@/components/Navigation/Dropdown.vue";
import DropdownContent from "@/components/Navigation/DropdownContent.vue";
import DropdownItem from "@/components/Navigation/DropdownItem.vue";
@@ -253,7 +261,10 @@ import Tag from "@/components/Navigation/Tag.vue";
import Topbar from "@/components/Navigation/Topbar.vue";
Vue.component("k-button", Button);
+Vue.component("k-button-disabled", ButtonDisabled);
Vue.component("k-button-group", ButtonGroup);
+Vue.component("k-button-link", ButtonLink);
+Vue.component("k-button-native", ButtonNative);
Vue.component("k-dropdown", Dropdown);
Vue.component("k-dropdown-content", DropdownContent);
Vue.component("k-dropdown-item", DropdownItem);
diff --git a/panel/src/config/directives.js b/panel/src/config/directives.js
deleted file mode 100644
index 3e8c3847a3..0000000000
--- a/panel/src/config/directives.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import tab from "@/directives/tab.js";
-
-export default {
- install(Vue) {
- // tab directive
- Vue.directive("tab", tab);
- }
-};
diff --git a/panel/src/config/events.js b/panel/src/config/events.js
index 01b605688d..47ef611660 100644
--- a/panel/src/config/events.js
+++ b/panel/src/config/events.js
@@ -1,4 +1,3 @@
-import { lcfirst } from "@/helpers/stringCase.js";
export default {
install(Vue) {
@@ -68,7 +67,7 @@ export default {
parts.push('shift');
}
- let key = lcfirst(e.key);
+ let key = this.$helper.string.lcfirst(e.key);
// key replacements
const keys = {
diff --git a/panel/src/config/helpers.js b/panel/src/config/helpers.js
new file mode 100644
index 0000000000..d1b26680b3
--- /dev/null
+++ b/panel/src/config/helpers.js
@@ -0,0 +1,25 @@
+import Vue from "vue";
+
+import "@/helpers/regex.js";
+
+import clone from "@/helpers/clone.js";
+import debounce from "@/helpers/debounce.js";
+import pad from "@/helpers/pad.js";
+import ratio from "@/helpers/ratio.js";
+import slug from "@/helpers/slug.js";
+import sort from "@/helpers/sort.js";
+import string from "@/helpers/string.js";
+import upload from "@/helpers/upload.js";
+import isUploadEvent from "@/helpers/isUploadEvent.js";
+
+Vue.prototype.$helper = {
+ clone: clone,
+ isUploadEvent: isUploadEvent,
+ debounce: debounce,
+ pad: pad,
+ ratio: ratio,
+ slug: slug,
+ sort: sort,
+ string: string,
+ upload: upload
+};
diff --git a/panel/src/config/libraries.js b/panel/src/config/libraries.js
new file mode 100644
index 0000000000..e44b8e05b5
--- /dev/null
+++ b/panel/src/config/libraries.js
@@ -0,0 +1,12 @@
+import Vue from "vue";
+
+import autosize from "autosize";
+
+import dayjs from "dayjs";
+import customParseFormat from 'dayjs/plugin/customParseFormat'
+dayjs.extend(customParseFormat);
+
+Vue.prototype.$library = {
+ autosize: autosize,
+ dayjs: dayjs
+};
diff --git a/panel/src/config/router.js b/panel/src/config/router.js
index 2c9eafbae6..b2a028bf79 100644
--- a/panel/src/config/router.js
+++ b/panel/src/config/router.js
@@ -28,8 +28,8 @@ router.beforeEach((to, from, next) => {
store.dispatch("view", to.meta.view);
// reset the content locks
- store.dispatch("form/lock", null);
- store.dispatch("form/unlock", null);
+ store.dispatch("content/lock", null);
+ store.dispatch("content/unlock", null);
// clear all heartbeats
store.dispatch("heartbeat/clear");
diff --git a/panel/src/config/routes.js b/panel/src/config/routes.js
index 74a8d7da7e..8235c65314 100644
--- a/panel/src/config/routes.js
+++ b/panel/src/config/routes.js
@@ -30,7 +30,7 @@ export default [
// remove all form changes from localStorage
Object.keys(localStorage).forEach(key => {
- if (key.startsWith("kirby$form")) {
+ if (key.startsWith("kirby$content$")) {
localStorage.removeItem(key);
}
});
diff --git a/panel/src/helpers/isUploadEvent.js b/panel/src/helpers/isUploadEvent.js
new file mode 100644
index 0000000000..5a5d8a46eb
--- /dev/null
+++ b/panel/src/helpers/isUploadEvent.js
@@ -0,0 +1,21 @@
+export default (event) => {
+
+ if (!event.dataTransfer) {
+ return false;
+ }
+
+ if (!event.dataTransfer.types) {
+ return false;
+ }
+
+ if (event.dataTransfer.types.includes("Files") !== true) {
+ return false;
+ }
+
+ if (event.dataTransfer.types.includes("text/plain") !== false) {
+ return false;
+ }
+
+ return true;
+
+};
diff --git a/panel/src/helpers/padZero.js b/panel/src/helpers/pad.js
similarity index 100%
rename from panel/src/helpers/padZero.js
rename to panel/src/helpers/pad.js
diff --git a/panel/src/helpers/ratioPadding.js b/panel/src/helpers/ratio.js
similarity index 100%
rename from panel/src/helpers/ratioPadding.js
rename to panel/src/helpers/ratio.js
diff --git a/panel/src/helpers/regex.js b/panel/src/helpers/regex.js
index 98e7fe1a86..768f600f80 100644
--- a/panel/src/helpers/regex.js
+++ b/panel/src/helpers/regex.js
@@ -1 +1 @@
-RegExp.escape = s => s.replace(/\p[-/\\^$*+?.()|[\]{}]/g, '\\$&');
+RegExp.escape = s => s.replace(/[\p{L}]|[-\/\\^$*+?.()|[\]{}]+/u, '\\$&');
diff --git a/panel/src/helpers/slug.js b/panel/src/helpers/slug.js
index 529207ae40..5a0af0e467 100644
--- a/panel/src/helpers/slug.js
+++ b/panel/src/helpers/slug.js
@@ -1,4 +1,4 @@
-import "./regex";
+import "./regex.js";
export default (string, rules = [], allowed = "") => {
diff --git a/panel/src/helpers/string.js b/panel/src/helpers/string.js
new file mode 100644
index 0000000000..1e4441b5d1
--- /dev/null
+++ b/panel/src/helpers/string.js
@@ -0,0 +1,11 @@
+
+export default {
+ ucfirst (string) {
+ const str = String(string);
+ return str.charAt(0).toUpperCase() + str.substr(1);
+ },
+ lcfirst (string) {
+ const str = String(string);
+ return str.charAt(0).toLowerCase() + str.substr(1);
+ }
+} ;
diff --git a/panel/src/helpers/stringCase.js b/panel/src/helpers/stringCase.js
deleted file mode 100644
index 7fb410a516..0000000000
--- a/panel/src/helpers/stringCase.js
+++ /dev/null
@@ -1,10 +0,0 @@
-
-export function ucfirst (string) {
- const str = String(string);
- return str.charAt(0).toUpperCase() + str.substr(1);
-}
-
-export function lcfirst (string) {
- const str = String(string);
- return str.charAt(0).toLowerCase() + str.substr(1);
-}
diff --git a/panel/src/helpers/uploadFile.js b/panel/src/helpers/upload.js
similarity index 100%
rename from panel/src/helpers/uploadFile.js
rename to panel/src/helpers/upload.js
diff --git a/panel/src/main.js b/panel/src/main.js
index f7c597a9ff..45bf69cf49 100644
--- a/panel/src/main.js
+++ b/panel/src/main.js
@@ -1,27 +1,28 @@
import App from "./App.vue";
-import Directives from "./config/directives.js";
import Filters from "./config/filters.js";
import Events from "./config/events.js";
import Vue from "vue";
import Vuelidate from "vuelidate";
-Vue.use(Directives);
-Vue.use(Events);
-Vue.use(Filters);
-Vue.use(Vuelidate);
-
Vue.config.productionTip = false;
Vue.config.devtools = true;
import "./config/components.js";
import "./config/api.js";
import "./config/errors.js";
+import "./config/helpers.js";
import "./config/i18n.js";
+import "./config/libraries.js";
import "./config/plugins.js";
+Vue.use(Events);
+Vue.use(Filters);
+Vue.use(Vuelidate);
+
import router from "./config/router.js";
import store from "./store/store.js";
+
new Vue({
router,
store,
@@ -32,6 +33,9 @@ import store from "./store/store.js";
window.panel.plugins.created.forEach(plugin => {
plugin(this);
});
+
+ // initialize content store
+ this.$store.dispatch("content/init");
},
render: h => {
return h(App);
diff --git a/panel/src/mixins/picker/dialog.js b/panel/src/mixins/picker/dialog.js
index c213b95e44..af22e4bff3 100644
--- a/panel/src/mixins/picker/dialog.js
+++ b/panel/src/mixins/picker/dialog.js
@@ -1,3 +1,5 @@
+import debounce from "@/helpers/debounce.js";
+
export default {
data() {
return {
@@ -10,6 +12,13 @@ export default {
multiple: true,
parent: null,
selected: [],
+ search: true
+ },
+ search: null,
+ pagination: {
+ limit: 20,
+ page: 1,
+ total: 0
}
}
},
@@ -21,12 +30,25 @@ export default {
return this.multiple === true ? "check" : "circle-filled";
}
},
+ watch: {
+ search: debounce(function () {
+ this.pagination.page = 0;
+ this.fetch();
+ }, 200),
+ },
methods: {
fetch() {
+ const params = {
+ page: this.pagination.page,
+ search: this.search,
+ ...this.fetchData || {}
+ };
+
return this.$api
- .get(this.options.endpoint, this.fetchData || {})
+ .get(this.options.endpoint, params)
.then(response => {
- this.models = response.data || response.pages || response;
+ this.models = response.data;
+ this.pagination = response.pagination;
if (this.onFetched) {
this.onFetched(response);
@@ -37,16 +59,22 @@ export default {
this.issue = e.message;
});
},
- open(files, options) {
+ open(models, options) {
+
+ // reset pagination
+ this.pagination.page = 0;
+
+ // reset the search
+ this.search = null;
let fetch = true;
- if (Array.isArray(files)) {
- this.models = files;
+ if (Array.isArray(models)) {
+ this.models = models;
fetch = false;
} else {
this.models = [];
- options = files;
+ options = models;
}
this.options = {
@@ -70,6 +98,11 @@ export default {
this.$refs.dialog.open();
}
},
+ paginate(pagination) {
+ this.pagination.page = pagination.page;
+ this.pagination.limit = pagination.limit;
+ this.fetch();
+ },
submit() {
this.$emit("submit", Object.values(this.selected));
this.$refs.dialog.close();
diff --git a/panel/src/mixins/picker/field.js b/panel/src/mixins/picker/field.js
index 83f2d875c6..09976f9dc7 100644
--- a/panel/src/mixins/picker/field.js
+++ b/panel/src/mixins/picker/field.js
@@ -10,6 +10,7 @@ export default {
max: Number,
multiple: Boolean,
parent: String,
+ search: Boolean,
size: String,
text: String,
value: {
@@ -43,6 +44,21 @@ export default {
return layouts["list"];
},
+ isInvalid() {
+ if (this.required && this.selected.length === 0) {
+ return true;
+ }
+
+ if (this.min && this.selected.length < this.min) {
+ return true;
+ }
+
+ if (this.max && this.selected.length > this.max) {
+ return true;
+ }
+
+ return false;
+ },
more() {
if (!this.max) {
return true;
diff --git a/panel/src/mixins/section/collection.js b/panel/src/mixins/section/collection.js
index 0290ceb0f1..d108100306 100644
--- a/panel/src/mixins/section/collection.js
+++ b/panel/src/mixins/section/collection.js
@@ -34,6 +34,17 @@ export default {
help() {
return this.options.help;
},
+ isInvalid() {
+ if (this.options.min && this.data.length < this.options.min) {
+ return true;
+ }
+
+ if (this.options.max && this.data.length > this.options.max) {
+ return true;
+ }
+
+ return false;
+ },
language() {
return this.$store.state.languages.current;
},
diff --git a/panel/src/mixins/tab.js b/panel/src/mixins/tab.js
new file mode 100644
index 0000000000..bd840f29cc
--- /dev/null
+++ b/panel/src/mixins/tab.js
@@ -0,0 +1,32 @@
+export default {
+ mounted() {
+ this.$el.addEventListener("keyup", this.onTab, true);
+ this.$el.addEventListener("blur", this.onUntab, true);
+ },
+ destroyed() {
+ this.$el.removeEventListener("keyup", this.onTab, true);
+ this.$el.removeEventListener("blur", this.onUntab, true);
+ },
+ methods: {
+ focus() {
+ if (this.$el.focus) {
+ this.$el.focus();
+ }
+ },
+ onTab(e) {
+ if (e.keyCode === 9) {
+ this.$el.setAttribute("data-tabbed", true);
+ }
+ },
+ onUntab() {
+ this.$el.removeAttribute("data-tabbed");
+ },
+ tab() {
+ this.$el.focus();
+ this.$el.setAttribute("data-tabbed", true);
+ },
+ untab() {
+ this.$el.removeAttribute("data-tabbed");
+ },
+ }
+};
diff --git a/panel/src/mixins/view/prevnext.js b/panel/src/mixins/view/prevnext.js
index 3ad0413cd2..12dc4ca6c0 100644
--- a/panel/src/mixins/view/prevnext.js
+++ b/panel/src/mixins/view/prevnext.js
@@ -1,7 +1,7 @@
export default {
computed: {
isLocked() {
- return this.$store.getters["form/lock"] !== null;
+ return this.$store.state.content.status.lock !== null;
}
},
created() {
diff --git a/panel/src/store/modules/content.js b/panel/src/store/modules/content.js
new file mode 100644
index 0000000000..b47a12a377
--- /dev/null
+++ b/panel/src/store/modules/content.js
@@ -0,0 +1,361 @@
+import Vue from "vue";
+import Api from "@/api/api.js";
+import clone from "@/helpers/clone.js";
+
+const keep = (id, data) => {
+ localStorage.setItem(
+ "kirby$content$" + id,
+ JSON.stringify(data)
+ );
+};
+
+export default {
+ namespaced: true,
+
+ state: {
+ /**
+ * ID of current model
+ */
+ current: null,
+
+ /**
+ * Object of models:
+ * Key => type/slug/language, e.g. pages/blog+a-blog-post/de
+ * Value => Object of
+ * - api: API endpoint
+ * - originals: values as they are in the content file
+ * - changes: values with unsaved changes
+ */
+ models: {},
+
+ /**
+ * Object of status flags/info
+ */
+ status: {
+ // whether form shall be disabled (e.g. for structure fields)
+ enabled: true,
+
+ // content lock info
+ lock: null,
+
+ // content unlock info
+ unlock: null
+ }
+ },
+
+
+ getters: {
+ // status getters
+
+ /**
+ * Checks for an ID if a model exists in the store
+ */
+ exists: state => id => {
+ return state.models.hasOwnProperty(id);
+ },
+ /**
+ * Checks for an ID if a model has unsaved changes
+ */
+ hasChanges: (state, getters) => id => {
+ const changes = getters.model(id).changes;
+ return Object.keys(changes).length > 0;
+ },
+ /**
+ * Checks for an ID if it is the current model
+ */
+ isCurrent: (state) => id => {
+ return state.current === id;
+ },
+
+ // data getters
+
+ /**
+ * Returns ID (current or provided) with correct language suffix
+ */
+ id: (state, getters, rootState) => id => {
+ id = id || state.current;
+
+ if (rootState.languages.current) {
+ return id + "/" + rootState.languages.current.code;
+ } else {
+ return id;
+ }
+ },
+ /**
+ * Return the full model object for passed ID
+ */
+ model: (state, getters) => id => {
+ id = id || state.current;
+
+ if (getters.exists(id) === true) {
+ return state.models[id];
+ }
+
+ return {
+ api: null,
+ originals: {},
+ values: {},
+ changes: {},
+ };
+ },
+ /**
+ * Returns original (in content file) values for passed model ID
+ */
+ originals: (state, getters) => id => {
+ return clone(getters.model(id).originals);
+ },
+ /**
+ * Returns values (incl. unsaved changes) for passed model ID
+ */
+ values: (state, getters) => id => {
+ return {
+ ...getters.originals(id),
+ ...getters.changes(id)
+ };
+ },
+ /**
+ * Returns unsaved changes for passed model ID
+ */
+ changes: (state, getters) => id => {
+ return clone(getters.model(id).changes);
+ }
+ },
+
+
+ mutations: {
+ CREATE(state, [id, model]) {
+ if (!model) {
+ return false;
+ }
+
+ // if model already in store, use stored changes,
+ // otherwise fallback to provided changes
+ let changes = state.models[id] ? state.models[id].changes : model.changes ;
+
+ Vue.set(state.models, id, {
+ api: model.api,
+ originals: model.originals,
+ changes: changes || {}
+ });
+ },
+ CURRENT(state, id) {
+ state.current = id;
+ },
+ LOCK(state, lock) {
+ Vue.set(state.status, "lock", lock);
+ },
+ MOVE(state, [from, to]) {
+ // move state
+ const model = clone(state.models[from]);
+ Vue.delete(state.models, from);
+ Vue.set(state.models, to, model);
+
+ // move local storage
+ const storage = localStorage.getItem("kirby$content$" + from);
+ localStorage.removeItem("kirby$content$" + from);
+ localStorage.setItem("kirby$content$" + to, storage);
+ },
+ REMOVE(state, id) {
+ Vue.delete(state.models, id);
+ localStorage.removeItem("kirby$content$" + id);
+ },
+ REVERT(state, id) {
+ if (state.models[id]) {
+ Vue.set(state.models[id], "changes", {});
+ localStorage.removeItem("kirby$content$" + id);
+ }
+ },
+ STATUS(state, enabled) {
+ Vue.set(state.status, "enabled", enabled);
+ },
+ UNLOCK(state, unlock) {
+ if (unlock) {
+ // reset unsaved changes if content has been unlocked by another user
+ Vue.set(state.models[state.current], "changes", {});
+ }
+
+ Vue.set(state.status, "unlock", unlock);
+ },
+ UPDATE(state, [id, field, value]) {
+ // avoid updating without a valid model
+ if (!state.models[id]) {
+ return false;
+ }
+
+ value = clone(value);
+
+ // compare current field value with its original value
+ const current = JSON.stringify(value);
+ const original = JSON.stringify(state.models[id].originals[field]);
+
+ if (original === current) {
+ // if the same, there are no unsaved changes
+ Vue.delete(state.models[id].changes, field);
+ } else {
+ // if they differ, set as unsaved change
+ Vue.set(state.models[id].changes, field, value);
+ }
+
+ keep(id, {
+ api: state.models[id].api,
+ originals: state.models[id].originals,
+ changes: state.models[id].changes
+ });
+ }
+ },
+
+
+ actions: {
+ init(context) {
+ // load models in store from localStorage
+ Object.keys(localStorage)
+ .filter(key => key.startsWith("kirby$content$"))
+ .map(key => key.split("kirby$content$")[1])
+ .forEach(id => {
+ const data = localStorage.getItem("kirby$content$" + id);
+ context.commit("CREATE", [id, JSON.parse(data)]);
+ });
+
+ // load old format
+ Object.keys(localStorage)
+ .filter(key => key.startsWith("kirby$form$"))
+ .map(key => key.split("kirby$form$")[1])
+ .forEach(id => {
+ const json = localStorage.getItem("kirby$form$" + id);
+ let data = null;
+
+ try {
+ data = JSON.parse(json);
+ } catch (e) {
+ // fail silently
+ }
+
+ if (!data || !data.api) {
+ // remove invalid entry
+ localStorage.removeItem("kirby$form$" + id);
+ return false;
+ }
+
+ const model = {
+ api: data.api,
+ originals: data.originals,
+ changes: data.values
+ };
+
+ // add it to the state
+ context.commit("CREATE", [id, model]);
+
+ // keep it in localStorage
+ keep(id, model);
+
+ // remove the old entry
+ localStorage.removeItem("kirby$form$" + id);
+ });
+ },
+ create(context, model) {
+ // attach the language to the id
+ model.id = context.getters.id(model.id);
+
+ // remove title from model content
+ if (model.id.startsWith("pages/") || model.id.startsWith("site")) {
+ delete model.content.title;
+ }
+
+ const data = {
+ api: model.api,
+ originals: clone(model.content),
+ changes: {}
+ };
+
+ // check if content was previously unlocked
+ Api
+ .get(model.api + "/unlock")
+ .then(response => {
+ if (
+ response.supported === true &&
+ response.unlocked === true
+ ) {
+ context.commit("UNLOCK", context.state.models[model.id].changes);
+ }
+ })
+ .catch(() => {
+ // fail silently
+ });
+
+ context.commit("CREATE", [model.id, data]);
+ context.dispatch("current", model.id);
+ },
+ current(context, id) {
+ context.commit("CURRENT", id);
+ },
+ disable(context) {
+ context.commit("STATUS", false);
+ },
+ enable(context) {
+ context.commit("STATUS", true);
+ },
+ lock(context, lock) {
+ context.commit("LOCK", lock);
+ },
+ move(context, [from, to]) {
+ from = context.getters.id(from);
+ to = context.getters.id(to);
+ context.commit("MOVE", [from, to]);
+ },
+ remove(context, id) {
+ context.commit("REMOVE", id);
+
+ if (context.getters.isCurrent(id)) {
+ context.commit("CURRENT", null);
+ }
+ },
+ revert(context, id) {
+ id = id || context.state.current;
+ context.commit("REVERT", id);
+ },
+ save(context, id) {
+ id = id || context.state.current;
+
+ // don't allow save if model is not current
+ // or the form is currently disabled
+ if (
+ context.getters.isCurrent(id) &&
+ context.state.status.enabled === false
+ ) {
+ return false;
+ }
+
+ // disable form while saving
+ context.dispatch("disable");
+
+ const model = context.getters.model(id);
+ const data = {...model.originals, ...model.changes};
+
+ // Send updated values to API
+ return Api
+ .patch(model.api, data)
+ .then(() => {
+ // re-create model with updated values as originals
+ context.commit("CREATE", [id, {
+ ...model,
+ originals: data
+ }]);
+
+ // revert unsaved changes (which also removes localStorage entry)
+ context.dispatch("revert", id);
+ context.dispatch("enable");
+ })
+ .catch(error => {
+ context.dispatch("enable");
+ throw error;
+ });
+ },
+ unlock(context, unlock) {
+ context.commit("UNLOCK", unlock);
+ },
+ update(context, [field, value, id]) {
+ id = id || context.state.current;
+ context.commit("UPDATE", [id, field, value]);
+ }
+ }
+};
diff --git a/panel/src/store/modules/form.js b/panel/src/store/modules/form.js
deleted file mode 100644
index a3d85538ab..0000000000
--- a/panel/src/store/modules/form.js
+++ /dev/null
@@ -1,247 +0,0 @@
-import Vue from "vue";
-import Api from "@/api/api.js";
-import clone from "@/helpers/clone.js";
-
-export default {
- namespaced: true,
- state: {
- models: {},
- current: null,
- isDisabled: false,
- lock: null,
- unlock: null
- },
- getters: {
- current: state => {
- return state.current;
- },
- exists: state => id => {
- return state.models.hasOwnProperty(id);
- },
- hasChanges: (state, getters) => id => {
- return Object.keys(getters.model(id).changes).length > 0;
- },
- id: (state, getters, rootState) => id => {
- if (rootState.languages.current) {
- return id + "/" + rootState.languages.current.code;
- } else {
- return id;
- }
- },
- isCurrent: (state) => id => {
- return state.current === id;
- },
- isDisabled: (state) => {
- return state.isDisabled === true;
- },
- lock: state => {
- return state.lock;
- },
- model: (state, getters) => id => {
- return getters.exists(id)
- ? state.models[id]
- : {
- originals: {},
- values: {},
- changes: {},
- api: null
- };
- },
- originals: (state, getters) => id => {
- return clone(getters.model(id).originals);
- },
- values: (state, getters) => id => {
- id = id || state.current;
- return clone(getters.model(id).values);
- },
- unlock: state => {
- return state.unlock;
- }
- },
- mutations: {
- CREATE(state, model) {
- Vue.set(state.models, model.id, {
- api: model.api,
- originals: clone(model.content),
- values: clone(model.content),
- changes: {}
- });
- },
- CURRENT(state, id) {
- state.current = id;
- },
- DELETE_CHANGES(state, id) {
- Vue.set(state.models[id], "changes", {});
- Vue.set(state.models[id], "values", clone(state.models[id].originals));
- localStorage.removeItem("kirby$form$" + id);
- },
- IS_DISABLED(state, disabled) {
- state.isDisabled = disabled;
- },
- LOCK(state, lock) {
- state.lock = lock;
- },
- MOVE(state, ids) {
- // move state
- const model = clone(state.models[ids.old]);
- Vue.delete(state.models, ids.old);
- Vue.set(state.models, ids.new, model);
-
- // move local storage
- const storage = localStorage.getItem("kirby$form$" + ids.old);
- localStorage.removeItem("kirby$form$" + ids.old);
- localStorage.setItem("kirby$form$" + ids.new, storage);
- },
- REMOVE(state, id) {
- Vue.delete(state.models, id);
- localStorage.removeItem("kirby$form$" + id);
- },
- SET_ORIGINALS(state, [id, originals]) {
- state.models[id].originals = clone(originals);
- },
- SET_VALUES(state, [id, values]) {
- state.models[id].values = clone(values);
- },
- UNLOCK(state, unlock) {
- state.unlock = unlock;
- },
- UPDATE(state, [id, field, value]) {
-
- // avoid updating without a valid model
- if (!state.models[id]) {
- return false;
- }
-
- value = clone(value);
-
- Vue.set(state.models[id].values, field, value);
-
- const original = JSON.stringify(state.models[id].originals[field]);
- const current = JSON.stringify(value);
-
- if (original === current) {
- Vue.delete(state.models[id].changes, field);
- } else {
- Vue.set(state.models[id].changes, field, true);
- }
-
- localStorage.setItem(
- "kirby$form$" + id,
- JSON.stringify({
- api: state.models[id].api,
- originals: state.models[id].originals,
- values: state.models[id].values,
- changes: state.models[id].changes
- })
- );
- }
- },
- actions: {
- create(context, model) {
- // attach the language to the id
- if (
- context.rootState.languages.current &&
- context.rootState.languages.current.code
- ) {
- model.id = context.getters.id(model.id);
- }
-
- if (model.id.startsWith("pages/") || model.id.startsWith("site")) {
- // remove title from model content
- delete model.content.title;
- }
-
- context.commit("CREATE", model);
- context.dispatch("current", model.id);
- context.dispatch("load", model);
- },
- current(context, id) {
- context.commit("CURRENT", id);
- },
- load(context, model) {
- const stored = localStorage.getItem("kirby$form$" + model.id);
-
- if (stored) {
- const data = JSON.parse(stored);
-
- Api.get(model.api + "/unlock").then(response => {
- if (
- response.supported === false ||
- response.unlocked === false
- ) {
- Object.keys(data.values).forEach(field => {
- const value = data.values[field];
- context.commit("UPDATE", [model.id, field, value]);
- });
- return;
- }
-
- context.commit("UNLOCK", data.values);
- });
- }
- },
- disable(context) {
- context.commit("IS_DISABLED", true);
- },
- enable(context) {
- context.commit("IS_DISABLED", false);
- },
- lock(context, lock) {
- context.commit("LOCK", lock);
- },
- move(context, ids) {
- context.commit("MOVE", ids);
- },
- remove(context, id) {
- context.commit("REMOVE", id);
- },
- revert(context, id) {
- const model = context.getters.model(id);
-
- // fetch from api
- return Api.get(model.api, { select: "content" }).then(response => {
-
- if (id.startsWith("pages/") || id.startsWith("site")) {
- // remove title from response content
- delete response.content.title;
- }
-
- context.commit("SET_ORIGINALS", [id, response.content]);
- context.commit("SET_VALUES", [id, response.content]);
- context.commit("DELETE_CHANGES", id);
- });
- },
- save(context, id) {
-
- id = id || context.state.current;
-
- const model = context.getters.model(id);
-
- if (context.getters.isCurrent(id)) {
- if (context.state.isDisabled) {
- return false;
- }
- }
-
- context.dispatch("disable");
-
- // Send to api
- return Api
- .patch(model.api, model.values)
- .then(() => {
- context.dispatch("revert", id);
- context.dispatch("enable");
- })
- .catch(error => {
- context.dispatch("enable");
- throw error;
- });
- },
- unlock(context, unlock) {
- context.commit("UNLOCK", unlock);
- },
- update(context, [id, field, value]) {
- context.commit("UPDATE", [id, field, value]);
- }
- }
-};
diff --git a/panel/src/store/modules/languages.js b/panel/src/store/modules/languages.js
index 28e293694f..aafe486bbd 100644
--- a/panel/src/store/modules/languages.js
+++ b/panel/src/store/modules/languages.js
@@ -12,10 +12,12 @@ export default {
state.all = languages.map(language => {
return {
code: language.code,
- name: language.name,
default: language.default,
direction: language.direction,
- rules: language.rules
+ locale: language.locale,
+ name: language.name,
+ rules: language.rules,
+ url: language.url
};
});
},
diff --git a/panel/src/store/store.js b/panel/src/store/store.js
index 87d86aa677..f94b75bf97 100644
--- a/panel/src/store/store.js
+++ b/panel/src/store/store.js
@@ -2,7 +2,7 @@ import Vue from "vue";
import Vuex from "vuex";
// store modules
-import form from "./modules/form.js";
+import content from "./modules/content.js";
import heartbeat from "./modules/heartbeat.js";
import languages from "./modules/languages.js";
import notification from "./modules/notification.js";
@@ -87,7 +87,7 @@ export default new Vuex.Store({
}
},
modules: {
- form: form,
+ content: content,
heartbeat: heartbeat,
languages: languages,
notification: notification,
diff --git a/panel/tests/unit/Helpers/PadZero.spec.js b/panel/tests/unit/Helpers/Pad.spec.js
similarity index 63%
rename from panel/tests/unit/Helpers/PadZero.spec.js
rename to panel/tests/unit/Helpers/Pad.spec.js
index e5e7728200..d100e286e7 100644
--- a/panel/tests/unit/Helpers/PadZero.spec.js
+++ b/panel/tests/unit/Helpers/Pad.spec.js
@@ -1,45 +1,44 @@
-import { mount } from "@vue/test-utils";
-import padZero from "@/helpers/padZero.js";
+import pad from "@/helpers/pad.js";
-describe("padZero Helper", () => {
+describe("pad Helper", () => {
it("default padding", () => {
- const result = padZero(1);
+ const result = pad(1);
expect(result).toBe("01");
});
it("default padding with unpadded number", () => {
- const result = padZero(10);
+ const result = pad(10);
expect(result).toBe("10");
});
it("default padding with higher number", () => {
- const result = padZero(120);
+ const result = pad(120);
expect(result).toBe("120");
});
it("default padding with zero", () => {
- const result = padZero(0);
+ const result = pad(0);
expect(result).toBe("00");
});
it("custom padding", () => {
- const result = padZero(1, 3);
+ const result = pad(1, 3);
expect(result).toBe("001");
});
it("custom padding with zero", () => {
- const result = padZero(0, 3);
+ const result = pad(0, 3);
expect(result).toBe("000");
});
it("custom padding with unpadded number", () => {
- const result = padZero(123, 3);
+ const result = pad(123, 3);
expect(result).toBe("123");
});
it("custom padding with higher number", () => {
- const result = padZero(1234, 3);
+ const result = pad(1234, 3);
expect(result).toBe("1234");
});
diff --git a/panel/tests/unit/Helpers/RatioPadding.spec.js b/panel/tests/unit/Helpers/Ratio.spec.js
similarity index 57%
rename from panel/tests/unit/Helpers/RatioPadding.spec.js
rename to panel/tests/unit/Helpers/Ratio.spec.js
index 7d8fdd05db..ec9be54d6b 100644
--- a/panel/tests/unit/Helpers/RatioPadding.spec.js
+++ b/panel/tests/unit/Helpers/Ratio.spec.js
@@ -1,34 +1,34 @@
-import ratioPadding from "@/helpers/ratioPadding.js";
+import ratio from "@/helpers/ratio.js";
-describe("ratioPadding Helper", () => {
+describe("ratio Helper", () => {
it("default ratio", () => {
- const result = ratioPadding();
+ const result = ratio();
expect(result).toBe("66.66666666666667%");
});
it("16/9", () => {
- const result = ratioPadding("16/9");
+ const result = ratio("16/9");
expect(result).toBe("56.25%");
});
it("invalid fraction 1", () => {
- const result = ratioPadding("0/16");
+ const result = ratio("0/16");
expect(result).toBe("100%");
});
it("invalid fraction 2", () => {
- const result = ratioPadding("16/0");
+ const result = ratio("16/0");
expect(result).toBe("100%");
});
it("invalid input 1", () => {
- const result = ratioPadding(1);
+ const result = ratio(1);
expect(result).toBe("100%");
});
it("invalid input 2", () => {
- const result = ratioPadding({});
+ const result = ratio({});
expect(result).toBe("100%");
});
diff --git a/panel/tests/unit/Helpers/Slug.spec.js b/panel/tests/unit/Helpers/Slug.spec.js
index ac6a688c81..23f831ee54 100644
--- a/panel/tests/unit/Helpers/Slug.spec.js
+++ b/panel/tests/unit/Helpers/Slug.spec.js
@@ -1,5 +1,4 @@
-import { mount } from '@vue/test-utils'
-import slug from '@/helpers/slug.js'
+import slug from "@/helpers/slug.js"
describe("Slug Helper", () => {
@@ -50,4 +49,13 @@ describe("Slug Helper", () => {
expect(result).toBe("aoess");
});
+ it("handles plus signs", () => {
+ const rules = [
+ { "+": "-plus-" }
+ ];
+
+ const result = slug("1+1", rules);
+ expect(result).toBe("1-plus-1");
+ });
+
});
diff --git a/panel/tests/unit/Helpers/StringCase.spec.js b/panel/tests/unit/Helpers/String.spec.js
similarity index 63%
rename from panel/tests/unit/Helpers/StringCase.spec.js
rename to panel/tests/unit/Helpers/String.spec.js
index 2b78c2b083..04627c4968 100644
--- a/panel/tests/unit/Helpers/StringCase.spec.js
+++ b/panel/tests/unit/Helpers/String.spec.js
@@ -1,34 +1,34 @@
-import { ucfirst, lcfirst } from '@/helpers/StringCase.js'
+import string from "@/helpers/string.js";
describe("String Case Helper", () => {
it("ucfirst", () => {
- const result = ucfirst("hello");
+ const result = string.ucfirst("hello");
expect(result).toBe("Hello");
});
it("ucfirst with single-char word", () => {
- const result = ucfirst("h");
+ const result = string.ucfirst("h");
expect(result).toBe("H");
});
it("ucfirst with wrong input", () => {
- const result = ucfirst(0);
+ const result = string.ucfirst(0);
expect(result).toBe("0");
});
it("lcfirst", () => {
- const result = lcfirst("Hello");
+ const result = string.lcfirst("Hello");
expect(result).toBe("hello");
});
it("lcfirst with single-char word", () => {
- const result = lcfirst("H");
+ const result = string.lcfirst("H");
expect(result).toBe("h");
});
it("lcfirst with wrong input", () => {
- const result = lcfirst(0);
+ const result = string.lcfirst(0);
expect(result).toBe("0");
});
diff --git a/panel/tests/unit/Navigation/Button.spec.js b/panel/tests/unit/Navigation/Button.spec.js
index 33f7ee8b5b..a20a0050ff 100644
--- a/panel/tests/unit/Navigation/Button.spec.js
+++ b/panel/tests/unit/Navigation/Button.spec.js
@@ -1,8 +1,14 @@
import { mount } from "@vue/test-utils";
import Vue from "vue";
import Button from "@/components/Navigation/Button.vue";
+import ButtonDisabled from "@/components/Navigation/ButtonDisabled.vue";
+import ButtonLink from "@/components/Navigation/ButtonLink.vue";
+import ButtonNative from "@/components/Navigation/ButtonNative.vue";
import Icon from "@/components/Misc/Icon.vue";
+Vue.component("k-button-disabled", ButtonDisabled);
+Vue.component("k-button-link", ButtonLink);
+Vue.component("k-button-native", ButtonNative);
Vue.component("k-icon", Icon);
describe("Button.vue", () => {
diff --git a/panel/tests/unit/Navigation/DropdownContent.spec.js b/panel/tests/unit/Navigation/DropdownContent.spec.js
index a1e3b2edce..d9329ddc5b 100644
--- a/panel/tests/unit/Navigation/DropdownContent.spec.js
+++ b/panel/tests/unit/Navigation/DropdownContent.spec.js
@@ -3,9 +3,11 @@ import Vue from "vue";
import DropdownContent from "@/components/Navigation/DropdownContent.vue";
import DropdownItem from "@/components/Navigation/DropdownItem.vue";
import Button from "@/components/Navigation/Button.vue";
+import ButtonNative from "@/components/Navigation/ButtonNative.vue";
Vue.component("k-dropdown-item", DropdownItem);
Vue.component("k-button", Button);
+Vue.component("k-button-native", ButtonNative);
const localVue = createLocalVue();
diff --git a/panel/tests/unit/Navigation/DropdownItem.spec.js b/panel/tests/unit/Navigation/DropdownItem.spec.js
index 73c4b69964..a43624e091 100644
--- a/panel/tests/unit/Navigation/DropdownItem.spec.js
+++ b/panel/tests/unit/Navigation/DropdownItem.spec.js
@@ -2,10 +2,16 @@ import { mount } from "@vue/test-utils";
import Vue from "vue";
import DropdownItem from "@/components/Navigation/DropdownItem.vue";
import Button from "@/components/Navigation/Button.vue";
+import ButtonDisabled from "@/components/Navigation/ButtonDisabled.vue";
+import ButtonLink from "@/components/Navigation/ButtonLink.vue";
+import ButtonNative from "@/components/Navigation/ButtonNative.vue";
import Link from "@/components/Navigation/Link.vue";
import Icon from "@/components/Misc/Icon.vue";
Vue.component("k-button", Button);
+Vue.component("k-button-disabled", ButtonDisabled);
+Vue.component("k-button-link", ButtonLink);
+Vue.component("k-button-native", ButtonNative);
Vue.component("k-link", Link);
Vue.component("k-icon", Icon);
@@ -56,8 +62,7 @@ describe("DropdownItem.vue", () => {
}
});
- expect(wrapper.element.tagName).toBe("BUTTON");
- expect(wrapper.attributes("disabled")).toBe("disabled");
+ expect(wrapper.is("span")).toBe(true);
});
it("disabled link", () => {
diff --git a/panel/tests/unit/Navigation/PrevNext.spec.js b/panel/tests/unit/Navigation/PrevNext.spec.js
index 55c7852875..2b3e525b02 100644
--- a/panel/tests/unit/Navigation/PrevNext.spec.js
+++ b/panel/tests/unit/Navigation/PrevNext.spec.js
@@ -3,11 +3,15 @@ import Vue from "vue";
import PrevNext from "@/components/Navigation/PrevNext.vue";
import Link from "@/components/Navigation/Link.vue";
import Button from "@/components/Navigation/Button.vue";
+import ButtonDisabled from "@/components/Navigation/ButtonDisabled.vue";
+import ButtonLink from "@/components/Navigation/ButtonLink.vue";
import ButtonGroup from "@/components/Navigation/ButtonGroup.vue";
import Icon from "@/components/Misc/Icon.vue";
Vue.component("k-link", Link);
Vue.component("k-button", Button);
+Vue.component("k-button-disabled", ButtonDisabled);
+Vue.component("k-button-link", ButtonLink);
Vue.component("k-button-group", ButtonGroup);
Vue.component("k-icon", Icon);
diff --git a/panel/tests/unit/Store/Content.spec.js b/panel/tests/unit/Store/Content.spec.js
new file mode 100644
index 0000000000..6fd8e454a5
--- /dev/null
+++ b/panel/tests/unit/Store/Content.spec.js
@@ -0,0 +1,181 @@
+import store from "@/store/store.js";
+
+describe("Content Store", () => {
+
+ it("default state", () => {
+
+ expect(store.state.content.current).toEqual(null);
+ expect(store.state.content.models).toEqual({});
+ expect(store.state.content.status.enabled).toEqual(true);
+ expect(store.state.content.status.lock).toEqual(null);
+ expect(store.state.content.status.unlock).toEqual(null);
+
+ });
+
+ it("default getters", () => {
+
+ expect(store.getters["content/exists"]("pages/test")).toEqual(false);
+ expect(store.getters["content/hasChanges"]("pages/test")).toEqual(false);
+ expect(store.getters["content/isCurrent"]("pages/test")).toEqual(false);
+ expect(store.getters["content/id"]("pages/test")).toEqual("pages/test");
+ expect(store.getters["content/model"]("pages/test")).toEqual({
+ api: null,
+ originals: {},
+ values: {},
+ changes: {},
+ });
+
+ expect(store.getters["content/originals"]("pages/test")).toEqual({});
+ expect(store.getters["content/values"]("pages/test")).toEqual({});
+ expect(store.getters["content/changes"]("pages/test")).toEqual({});
+
+ });
+
+ it("set current", () => {
+ expect(store.state.content.current).toEqual(null);
+ store.dispatch("content/current", "pages/test");
+ expect(store.getters["content/isCurrent"]("pages/test")).toEqual(true);
+ });
+
+ it("enable/disable content editing", () => {
+ expect(store.state.content.status.enabled).toEqual(true);
+ store.dispatch("content/disable");
+ expect(store.state.content.status.enabled).toEqual(false);
+ store.dispatch("content/enable");
+ expect(store.state.content.status.enabled).toEqual(true);
+ });
+
+ it("create and remove", () => {
+
+ expect(store.getters["content/exists"]("pages/test")).toEqual(false);
+
+ // use commit, because dispatch makes an API request
+ store.commit("content/CREATE", ["pages/test", {
+ api: "pages/test",
+ originals: {
+ title: "Test"
+ }
+ }]);
+
+ expect(store.getters["content/exists"]("pages/test")).toEqual(true);
+ expect(store.getters["content/model"]("pages/test")).toEqual({
+ api: "pages/test",
+ changes: {},
+ originals: {
+ title: "Test"
+ }
+ });
+
+ // remove the model from the store again
+ store.dispatch("content/remove", "pages/test");
+
+ expect(store.getters["content/exists"]("pages/test")).toEqual(false);
+
+ });
+
+ it("create, set current and remove", () => {
+
+ expect(store.getters["content/exists"]("pages/test")).toEqual(false);
+
+ // use commit, because dispatch makes an API request
+ store.commit("content/CREATE", ["pages/test", {
+ api: "pages/test",
+ originals: {
+ title: "Test"
+ }
+ }]);
+
+ store.dispatch("content/current", "pages/test");
+
+ expect(store.getters["content/isCurrent"]("pages/test")).toEqual(true);
+ expect(store.getters["content/exists"]("pages/test")).toEqual(true);
+
+ // remove the model from the store again
+ store.dispatch("content/remove", "pages/test");
+
+ expect(store.getters["content/isCurrent"]("pages/test")).toEqual(false);
+ expect(store.getters["content/exists"]("pages/test")).toEqual(false);
+ });
+
+ it("create and move", () => {
+
+ // use commit, because dispatch makes an API request
+ store.commit("content/CREATE", ["pages/a", {
+ api: "pages/test",
+ originals: {
+ title: "Test"
+ }
+ }]);
+
+ expect(store.getters["content/exists"]("pages/a")).toEqual(true);
+ expect(store.getters["content/exists"]("pages/b")).toEqual(false);
+
+ // move the model to a new key
+ store.dispatch("content/move", ["pages/a", "pages/b"]);
+
+ expect(store.getters["content/exists"]("pages/a")).toEqual(false);
+ expect(store.getters["content/exists"]("pages/b")).toEqual(true);
+
+ // clean up
+ store.dispatch("content/remove", "pages/b");
+
+ });
+
+ it("create, update and revert", () => {
+
+ // use commit, because dispatch makes an API request
+ store.commit("content/CREATE", ["pages/test", {
+ api: "pages/test",
+ originals: {
+ title: "Test"
+ }
+ }]);
+
+ expect(store.getters["content/originals"]("pages/test")).toEqual({
+ title: "Test"
+ });
+
+ expect(store.getters["content/values"]("pages/test")).toEqual({
+ title: "Test"
+ });
+
+ expect(store.getters["content/changes"]("pages/test")).toEqual({});
+ expect(store.getters["content/hasChanges"]("pages/test")).toEqual(false);
+
+ // make some changes
+ store.dispatch("content/update", ["title", "Updated", "pages/test"]);
+
+ expect(store.getters["content/originals"]("pages/test")).toEqual({
+ title: "Test"
+ });
+
+ expect(store.getters["content/values"]("pages/test")).toEqual({
+ title: "Updated"
+ });
+
+ expect(store.getters["content/changes"]("pages/test")).toEqual({
+ title: "Updated"
+ });
+
+ expect(store.getters["content/hasChanges"]("pages/test")).toEqual(true);
+
+ // revert changes
+ store.dispatch("content/revert", "pages/test");
+
+ expect(store.getters["content/originals"]("pages/test")).toEqual({
+ title: "Test"
+ });
+
+ expect(store.getters["content/values"]("pages/test")).toEqual({
+ title: "Test"
+ });
+
+ expect(store.getters["content/changes"]("pages/test")).toEqual({});
+ expect(store.getters["content/hasChanges"]("pages/test")).toEqual(false);
+
+ // clean up
+ store.dispatch("content/remove", "pages/test");
+
+ });
+
+});
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 0000000000..152ea5ec9a
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,21 @@
+parameters:
+ paths:
+ - %currentWorkingDirectory%
+ autoload_files:
+ - %currentWorkingDirectory%/vendor/autoload.php
+ - %rootDir%/../../autoload.php
+ autoload_directories:
+ - %currentWorkingDirectory%/tests
+ excludes_analyse:
+ - %currentWorkingDirectory%/dependencies
+ - %currentWorkingDirectory%/tests/*/fixtures/*
+ - %currentWorkingDirectory%/vendor
+ - %currentWorkingDirectory%/views
+
+ level: 0
+ memory_limit: 2G
+
+ ignoreErrors:
+ # we use bound $this in our callbacks
+ - message: '#(Using \$this outside a class\.|Undefined variable: \$this)#'
+ path: %currentWorkingDirectory%/config
diff --git a/src/Api/Api.php b/src/Api/Api.php
index 1610de621d..87a62ed5bf 100644
--- a/src/Api/Api.php
+++ b/src/Api/Api.php
@@ -8,6 +8,7 @@
use Kirby\Http\Response;
use Kirby\Http\Router;
use Kirby\Toolkit\F;
+use Kirby\Toolkit\Pagination;
use Kirby\Toolkit\Properties;
use Kirby\Toolkit\Str;
use Throwable;
@@ -38,7 +39,7 @@ class Api
/**
* Debugging flag
*
- * @var boolean
+ * @var bool
*/
protected $debug = false;
@@ -200,8 +201,16 @@ public function call(string $path = null, string $method = 'GET', array $request
}
}
+ // don't throw pagination errors if pagination
+ // page is out of bounds
+ $validate = Pagination::$validate;
+ Pagination::$validate = false;
+
$output = $this->route->action()->call($this, ...$this->route->arguments());
+ // restore old pagination validation mode
+ Pagination::$validate = $validate;
+
if (is_object($output) === true && is_a($output, 'Kirby\\Http\\Response') !== true) {
return $this->resolve($output)->toResponse();
}
@@ -268,7 +277,7 @@ public function data($key = null, ...$args)
/**
* Returns the debugging flag
*
- * @return boolean
+ * @return bool
*/
public function debug(): bool
{
@@ -279,7 +288,7 @@ public function debug(): bool
* Checks if injected data exists for the given key
*
* @param string $key
- * @return boolean
+ * @return bool
*/
public function hasData(string $key): bool
{
@@ -489,7 +498,7 @@ protected function setData(array $data = null)
/**
* Setter for the debug flag
*
- * @param boolean $debug
+ * @param bool $debug
* @return self
*/
protected function setDebug(bool $debug = false)
@@ -693,7 +702,7 @@ public function responseForException($e): array
* Upload helper method
*
* @param Closure $callback
- * @param boolean $single
+ * @param bool $single
* @return array
*
* @throws Exception If request has no files
diff --git a/src/Cache/ApcuCache.php b/src/Cache/ApcuCache.php
index 96011c7804..e750d20ee9 100644
--- a/src/Cache/ApcuCache.php
+++ b/src/Cache/ApcuCache.php
@@ -2,7 +2,7 @@
namespace Kirby\Cache;
-use APCUIterator;
+use APCuIterator;
/**
* APCu Cache Driver
@@ -19,7 +19,7 @@ class ApcuCache extends Cache
* Determines if an item exists in the cache
*
* @param string $key
- * @return boolean
+ * @return bool
*/
public function exists(string $key): bool
{
@@ -30,12 +30,12 @@ public function exists(string $key): bool
* Flushes the entire cache and returns
* whether the operation was successful
*
- * @return boolean
+ * @return bool
*/
public function flush(): bool
{
if (empty($this->options['prefix']) === false) {
- return apcu_delete(new APCUIterator('!^' . preg_quote($this->options['prefix']) . '!'));
+ return apcu_delete(new APCuIterator('!^' . preg_quote($this->options['prefix']) . '!'));
} else {
return apcu_clear_cache();
}
@@ -46,7 +46,7 @@ public function flush(): bool
* whether the operation was successful
*
* @param string $key
- * @return boolean
+ * @return bool
*/
public function remove(string $key): bool
{
@@ -77,7 +77,7 @@ public function retrieve(string $key)
* @param string $key
* @param mixed $value
* @param int $minutes
- * @return boolean
+ * @return bool
*/
public function set(string $key, $value, int $minutes = 0): bool
{
diff --git a/src/Cache/Cache.php b/src/Cache/Cache.php
index 5e7e06ba29..729d61b353 100644
--- a/src/Cache/Cache.php
+++ b/src/Cache/Cache.php
@@ -45,14 +45,14 @@ public function __construct(array $options = [])
* @param string $key
* @param mixed $value
* @param int $minutes
- * @return boolean
+ * @return bool
*/
abstract public function set(string $key, $value, int $minutes = 0): bool;
/**
* Adds the prefix to the key if given
*
- * @param string $key
+ * @param string $key
* @return string
*/
protected function key(string $key): string
@@ -152,7 +152,7 @@ public function expires(string $key)
* Checks if an item in the cache is expired
*
* @param string $key
- * @return boolean
+ * @return bool
*/
public function expired(string $key): bool
{
@@ -204,7 +204,7 @@ public function modified(string $key)
* Determines if an item exists in the cache
*
* @param string $key
- * @return boolean
+ * @return bool
*/
public function exists(string $key): bool
{
@@ -217,7 +217,7 @@ public function exists(string $key): bool
* this needs to be defined by the driver
*
* @param string $key
- * @return boolean
+ * @return bool
*/
abstract public function remove(string $key): bool;
@@ -226,7 +226,7 @@ abstract public function remove(string $key): bool;
* whether the operation was successful;
* this needs to be defined by the driver
*
- * @return boolean
+ * @return bool
*/
abstract public function flush(): bool;
diff --git a/src/Cache/FileCache.php b/src/Cache/FileCache.php
index 9f0d3738d4..1e50ff44ca 100644
--- a/src/Cache/FileCache.php
+++ b/src/Cache/FileCache.php
@@ -78,7 +78,7 @@ protected function file(string $key): string
* @param string $key
* @param mixed $value
* @param int $minutes
- * @return boolean
+ * @return bool
*/
public function set(string $key, $value, int $minutes = 0): bool
{
@@ -125,7 +125,7 @@ public function created(string $key)
* whether the operation was successful
*
* @param string $key
- * @return boolean
+ * @return bool
*/
public function remove(string $key): bool
{
@@ -142,7 +142,7 @@ public function remove(string $key): bool
* Flushes the entire cache and returns
* whether the operation was successful
*
- * @return boolean
+ * @return bool
*/
public function flush(): bool
{
diff --git a/src/Cache/MemCached.php b/src/Cache/MemCached.php
index 4c459c56c6..82cff0998f 100644
--- a/src/Cache/MemCached.php
+++ b/src/Cache/MemCached.php
@@ -52,7 +52,7 @@ public function __construct(array $options = [])
* @param string $key
* @param mixed $value
* @param int $minutes
- * @return boolean
+ * @return bool
*/
public function set(string $key, $value, int $minutes = 0): bool
{
@@ -76,7 +76,7 @@ public function retrieve(string $key)
* whether the operation was successful
*
* @param string $key
- * @return boolean
+ * @return bool
*/
public function remove(string $key): bool
{
@@ -88,7 +88,7 @@ public function remove(string $key): bool
* whether the operation was successful;
* WARNING: Memcached only supports flushing the whole cache at once!
*
- * @return boolean
+ * @return bool
*/
public function flush(): bool
{
diff --git a/src/Cache/MemoryCache.php b/src/Cache/MemoryCache.php
index bd4cac7d0a..7f2d098dac 100644
--- a/src/Cache/MemoryCache.php
+++ b/src/Cache/MemoryCache.php
@@ -31,7 +31,7 @@ class MemoryCache extends Cache
* @param string $key
* @param mixed $value
* @param int $minutes
- * @return boolean
+ * @return bool
*/
public function set(string $key, $value, int $minutes = 0): bool
{
@@ -56,7 +56,7 @@ public function retrieve(string $key)
* whether the operation was successful
*
* @param string $key
- * @return boolean
+ * @return bool
*/
public function remove(string $key): bool
{
@@ -72,7 +72,7 @@ public function remove(string $key): bool
* Flushes the entire cache and returns
* whether the operation was successful
*
- * @return boolean
+ * @return bool
*/
public function flush(): bool
{
diff --git a/src/Cache/NullCache.php b/src/Cache/NullCache.php
index c0c47dd480..a33fc9cdd1 100644
--- a/src/Cache/NullCache.php
+++ b/src/Cache/NullCache.php
@@ -25,7 +25,7 @@ class NullCache extends Cache
* @param string $key
* @param mixed $value
* @param int $minutes
- * @return boolean
+ * @return bool
*/
public function set(string $key, $value, int $minutes = 0): bool
{
@@ -49,7 +49,7 @@ public function retrieve(string $key)
* whether the operation was successful
*
* @param string $key
- * @return boolean
+ * @return bool
*/
public function remove(string $key): bool
{
@@ -60,7 +60,7 @@ public function remove(string $key): bool
* Flushes the entire cache and returns
* whether the operation was successful
*
- * @return boolean
+ * @return bool
*/
public function flush(): bool
{
diff --git a/src/Cms/Api.php b/src/Cms/Api.php
index 255e1693b1..08c9a9e59a 100644
--- a/src/Cms/Api.php
+++ b/src/Cms/Api.php
@@ -37,9 +37,7 @@ public function call(string $path = null, string $method = 'GET', array $request
$this->setRequestMethod($method);
$this->setRequestData($requestData);
- if ($languageCode = $this->language()) {
- $this->kirby->setCurrentLanguage($languageCode);
- }
+ $this->kirby->setCurrentLanguage($this->language());
if ($user = $this->kirby->user()) {
$this->kirby->setCurrentTranslation($user->language());
diff --git a/src/Cms/App.php b/src/Cms/App.php
index df6746db74..7bdc7e0d52 100644
--- a/src/Cms/App.php
+++ b/src/Cms/App.php
@@ -4,6 +4,7 @@
use Kirby\Data\Data;
use Kirby\Email\PHPMailer as Emailer;
+use Kirby\Exception\ErrorPageException;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\NotFoundException;
use Kirby\Http\Request;
@@ -56,6 +57,7 @@ class App
protected $languages;
protected $locks;
protected $multilang;
+ protected $nonce;
protected $options;
protected $path;
protected $request;
@@ -120,9 +122,15 @@ public function __construct(array $props = [])
$this->extensionsFromOptions();
$this->extensionsFromFolders();
+ // trigger hook for use in plugins
+ $this->trigger('system.loadPlugins:after');
+
// handle those damn errors
$this->handleErrors();
+ // execute a ready callback from the config
+ $this->optionsFromReadyCallback();
+
// bake config
Config::$data = $this->options;
}
@@ -475,7 +483,7 @@ public function email($preset = [], array $props = [])
*
* @param string $path
* @param mixed $parent
- * @param boolean $drafts
+ * @param bool $drafts
* @return \Kirby\Cms\File|null
*/
public function file(string $path, $parent = null, bool $drafts = true)
@@ -586,7 +594,11 @@ public function io($input)
// Pages
if (is_a($input, 'Kirby\Cms\Page')) {
- $html = $input->render();
+ try {
+ $html = $input->render();
+ } catch (ErrorPageException $e) {
+ return $this->io($e);
+ }
if ($input->isErrorPage() === true) {
if ($response->code() === null) {
@@ -758,7 +770,7 @@ public function markdown(string $text = null, bool $inline = false): string
/**
* Check for a multilang setup
*
- * @return boolean
+ * @return bool
*/
public function multilang(): bool
{
@@ -769,6 +781,17 @@ public function multilang(): bool
return $this->multilang = $this->languages()->count() !== 0;
}
+ /**
+ * Returns the nonce, which is used
+ * in the panel for inline scripts
+ *
+ * @return string
+ */
+ public function nonce(): string
+ {
+ return $this->nonce = $this->nonce ?? base64_encode(random_bytes(20));
+ }
+
/**
* Load a specific configuration option
*
@@ -791,17 +814,6 @@ public function options(): array
return $this->options;
}
- /**
- * Inject options from Kirby instance props
- *
- * @param array $options
- * @return array
- */
- protected function optionsFromProps(array $options = []): array
- {
- return $this->options = array_replace_recursive($this->options, $options);
- }
-
/**
* Load all options from files in site/config
*
@@ -823,16 +835,49 @@ protected function optionsFromConfig(): array
return $this->options = array_replace_recursive($config, $main, $host, $addr);
}
+ /**
+ * Inject options from Kirby instance props
+ *
+ * @param array $options
+ * @return array
+ */
+ protected function optionsFromProps(array $options = []): array
+ {
+ return $this->options = array_replace_recursive($this->options, $options);
+ }
+
+ /**
+ * Merge last-minute options from ready callback
+ *
+ * @return array
+ */
+ protected function optionsFromReadyCallback(): array
+ {
+ if (isset($this->options['ready']) === true && is_callable($this->options['ready']) === true) {
+ // fetch last-minute options from the callback
+ $options = (array)$this->options['ready']($this);
+
+ // inject all last-minute options recursively
+ $this->options = array_replace_recursive($this->options, $options);
+ }
+
+ return $this->options;
+ }
+
/**
* Returns any page from the content folder
*
- * @param string $id
+ * @param string $id|null
* @param \Kirby\Cms\Page|\Kirby\Cms\Site|null $parent
* @param bool $drafts
* @return \Kirby\Cms\Page|null
*/
- public function page(string $id, $parent = null, bool $drafts = true)
+ public function page(?string $id = null, $parent = null, bool $drafts = true)
{
+ if ($id === null) {
+ return null;
+ }
+
$parent = $parent ?? $this->site();
if ($page = $parent->find($id)) {
@@ -1184,10 +1229,20 @@ public function smartypants(string $text = null): string
{
$options = $this->option('smartypants', []);
- if ($options === true) {
+ if ($options === false) {
+ return $text;
+ } elseif (is_array($options) === false) {
$options = [];
}
+ if ($this->multilang() === true) {
+ $languageSmartypants = $this->language()->smartypants() ?? [];
+
+ if (empty($languageSmartypants) === false) {
+ $options = array_merge($options, $languageSmartypants);
+ }
+ }
+
return $this->component('smartypants')($this, $text, $options);
}
diff --git a/src/Cms/AppErrors.php b/src/Cms/AppErrors.php
index 7c90c3a8bf..6936d0d6eb 100644
--- a/src/Cms/AppErrors.php
+++ b/src/Cms/AppErrors.php
@@ -29,18 +29,17 @@ protected function handleCliErrors(): void
protected function handleErrors()
{
- $request = $this->request();
-
- // TODO: implement acceptance
- if ($request->ajax()) {
- return $this->handleJsonErrors();
+ if ($this->request()->cli() === true) {
+ $this->handleCliErrors();
+ return;
}
- if ($request->cli()) {
- return $this->handleCliErrors();
+ if ($this->visitor()->prefersJson() === true) {
+ $this->handleJsonErrors();
+ return;
}
- return $this->handleHtmlErrors();
+ $this->handleHtmlErrors();
}
protected function handleHtmlErrors()
diff --git a/src/Cms/AppPlugins.php b/src/Cms/AppPlugins.php
index 5121f43dd5..6b5e72d174 100644
--- a/src/Cms/AppPlugins.php
+++ b/src/Cms/AppPlugins.php
@@ -701,7 +701,6 @@ public function plugins(array $plugins = null): array
protected function pluginsLoader(): array
{
$root = $this->root('plugins');
- $kirby = $this;
$loaded = [];
foreach (Dir::read($root) as $dirname) {
@@ -709,14 +708,10 @@ protected function pluginsLoader(): array
continue;
}
- if (is_dir($root . '/' . $dirname) === false) {
- continue;
- }
-
$dir = $root . '/' . $dirname;
$entry = $dir . '/index.php';
- if (file_exists($entry) === false) {
+ if (is_dir($dir) !== true || is_file($entry) !== true) {
continue;
}
diff --git a/src/Cms/AppTranslations.php b/src/Cms/AppTranslations.php
index 5c898c4f73..073addffb0 100644
--- a/src/Cms/AppTranslations.php
+++ b/src/Cms/AppTranslations.php
@@ -158,7 +158,7 @@ public function translation(string $locale = null)
$inject = $this->extensions['translations'][$locale] ?? [];
// load from disk instead
- return Translation::load($locale, $this->root('translations') . '/' . $locale . '.json', $inject);
+ return Translation::load($locale, $this->root('i18n:translations') . '/' . $locale . '.json', $inject);
}
/**
@@ -172,6 +172,6 @@ public function translations()
return $this->translations;
}
- return Translations::load($this->root('translations'), $this->extensions['translations'] ?? []);
+ return Translations::load($this->root('i18n:translations'), $this->extensions['translations'] ?? []);
}
}
diff --git a/src/Cms/AppUsers.php b/src/Cms/AppUsers.php
index 54135d57e1..98697f27ad 100644
--- a/src/Cms/AppUsers.php
+++ b/src/Cms/AppUsers.php
@@ -77,7 +77,7 @@ protected function setUsers(array $users = null)
* Returns a specific user by id
* or the current user if no id is given
*
- * @param string $id
+ * @param string $id
* @return \Kirby\Cms\User|null
*/
public function user(string $id = null)
diff --git a/src/Cms/Auth.php b/src/Cms/Auth.php
index e90d38f52d..1b8089a126 100644
--- a/src/Cms/Auth.php
+++ b/src/Cms/Auth.php
@@ -165,7 +165,7 @@ public function ipHash(): string
* Check if logins are blocked for the current ip or email
*
* @param string $email
- * @return boolean
+ * @return bool
*/
public function isBlocked(string $email): bool
{
@@ -195,7 +195,7 @@ public function isBlocked(string $email): bool
*
* @param string $email
* @param string $password
- * @param boolean $long
+ * @param bool $long
* @return \Kirby\Cms\User
*
* @throws PermissionException If the rate limit was exceeded or if any other error occured with debug mode off
@@ -243,7 +243,7 @@ public function validatePassword(string $email, string $password)
$message = 'Invalid email or password';
}
- throw new PermissionException($message, 403);
+ throw new PermissionException($message);
}
// validate the user
@@ -334,7 +334,7 @@ public function log(): array
/**
* Logout the current user
*
- * @return boolean
+ * @return bool
*/
public function logout(): bool
{
@@ -354,7 +354,7 @@ public function logout(): bool
* Tracks a login
*
* @param string $email
- * @return boolean
+ * @return bool
*/
public function track(string $email): bool
{
diff --git a/src/Cms/Blueprint.php b/src/Cms/Blueprint.php
index ffa3a2f62c..fb7003de35 100644
--- a/src/Cms/Blueprint.php
+++ b/src/Cms/Blueprint.php
@@ -472,7 +472,7 @@ public static function fieldError(string $name, string $message): array
return [
'label' => 'Error',
'name' => $name,
- 'text' => $message,
+ 'text' => strip_tags($message),
'theme' => 'negative',
'type' => 'info',
];
@@ -595,12 +595,17 @@ protected function normalizeSections(string $tabName, array $sections): array
continue;
}
+ // fallback to default props when true is passed
+ if ($sectionProps === true) {
+ $sectionProps = [];
+ }
+
// inject all section extensions
$sectionProps = $this->extend($sectionProps);
$sections[$sectionName] = $sectionProps = array_merge($sectionProps, [
'name' => $sectionName,
- 'type' => $type = $sectionProps['type'] ?? null
+ 'type' => $type = $sectionProps['type'] ?? $sectionName
]);
if (empty($type) === true || is_string($type) === false) {
diff --git a/src/Cms/Collection.php b/src/Cms/Collection.php
index 7f6e0deed8..7f65b95c81 100644
--- a/src/Cms/Collection.php
+++ b/src/Cms/Collection.php
@@ -38,8 +38,8 @@ class Collection extends BaseCollection
/**
* Magic getter function
*
- * @param string $key
- * @param mixed $arguments
+ * @param string $key
+ * @param mixed $arguments
* @return mixed
*/
public function __call(string $key, $arguments)
@@ -101,8 +101,8 @@ public function add($object)
/**
* Appends an element to the data array
*
- * @param mixed $key Optional collection key, will be determined from the item if not given
- * @param mixed $item
+ * @param mixed $key Optional collection key, will be determined from the item if not given
+ * @param mixed $item
* @return \Kirby\Cms\Collection
*/
public function append(...$args)
@@ -165,7 +165,7 @@ public function groupBy($field, bool $i = true)
* is in the collection
*
* @param string|object $id
- * @return boolean
+ * @return bool
*/
public function has($id): bool
{
@@ -181,7 +181,7 @@ public function has($id): bool
* The method will automatically detect objects
* or ids and then search accordingly.
*
- * @param string|object $object
+ * @param string|object $object
* @return int
*/
public function indexOf($object): int
@@ -196,7 +196,7 @@ public function indexOf($object): int
/**
* Returns a Collection without the given element(s)
*
- * @param mixed ...$keys any number of keys, passed as individual arguments
+ * @param mixed ...$keys any number of keys, passed as individual arguments
* @return \Kirby\Cms\Collection
*/
public function not(...$keys)
@@ -216,7 +216,7 @@ public function not(...$keys)
/**
* Add pagination and return a sliced set of data.
*
- * @param mixed ...$arguments
+ * @param mixed ...$arguments
* @return \Kirby\Cms\Collection
*/
public function paginate(...$arguments)
@@ -240,9 +240,9 @@ public function parent()
/**
* Prepends an element to the data array
*
- * @param mixed $key Optional collection key, will be determined from the item if not given
- * @param mixed $item
- * @return Kirby\Cms\Collection
+ * @param mixed $key Optional collection key, will be determined from the item if not given
+ * @param mixed $item
+ * @return \Kirby\Cms\Collection
*/
public function prepend(...$args)
{
@@ -321,7 +321,7 @@ public function search(string $query = null, $params = [])
* to an array. This can also take a callback
* function to further modify the array result.
*
- * @param Closure $map
+ * @param Closure $map
* @return array
*/
public function toArray(Closure $map = null): array
diff --git a/src/Cms/Collections.php b/src/Cms/Collections.php
index 5f09e4d523..8a42ce2fda 100644
--- a/src/Cms/Collections.php
+++ b/src/Cms/Collections.php
@@ -42,8 +42,8 @@ class Collections
* Magic caller to enable something like
* `$collections->myCollection()`
*
- * @param string $name
- * @param array $arguments
+ * @param string $name
+ * @param array $arguments
* @return \Kirby\Cms\Collection|null
*/
public function __call(string $name, array $arguments = [])
@@ -89,7 +89,7 @@ public function get(string $name, array $data = [])
* Checks if a collection exists
*
* @param string $name
- * @return boolean
+ * @return bool
*/
public function has(string $name): bool
{
@@ -109,7 +109,7 @@ public function has(string $name): bool
* Loads collection from php file in a
* given directory or from plugin extension.
*
- * @param string $name
+ * @param string $name
* @return mixed
*/
public function load(string $name)
diff --git a/src/Cms/Content.php b/src/Cms/Content.php
index 52eb39e987..e55d84af56 100644
--- a/src/Cms/Content.php
+++ b/src/Cms/Content.php
@@ -69,7 +69,7 @@ public function __construct(array $data = [], $parent = null)
* Same as `self::data()` to improve
* `var_dump` output
*
- * @see self::data()
+ * @see self::data()
* @return array
*/
public function __debugInfo(): array
@@ -146,7 +146,7 @@ public function fields(): array
* Returns either a single field object
* or all registered fields
*
- * @param string $key
+ * @param string $key
* @return \Kirby\Cms\Field|array
*/
public function get(string $key = null)
@@ -172,7 +172,7 @@ public function get(string $key = null)
* Checks if a content field is set
*
* @param string $key
- * @return boolean
+ * @return bool
*/
public function has(string $key): bool
{
@@ -197,7 +197,7 @@ public function keys(): array
* without the fields, specified by the
* passed key(s)
*
- * @param string ...$keys
+ * @param string ...$keys
* @return self
*/
public function not(...$keys)
@@ -238,8 +238,8 @@ public function setParent(Model $parent)
/**
* Returns the raw data array
*
- * @see self::data()
- * @return array
+ * @see self::data()
+ * @return array
*/
public function toArray(): array
{
@@ -250,8 +250,8 @@ public function toArray(): array
* Updates the content and returns
* a cloned object
*
- * @param array $content
- * @param bool $overwrite
+ * @param array $content
+ * @param bool $overwrite
* @return self
*/
public function update(array $content = null, bool $overwrite = false)
diff --git a/src/Cms/ContentLock.php b/src/Cms/ContentLock.php
index a8f7d7ae50..44ec6c4846 100644
--- a/src/Cms/ContentLock.php
+++ b/src/Cms/ContentLock.php
@@ -85,7 +85,7 @@ public function get()
'user' => $user->id(),
'email' => $user->email(),
'time' => $time,
- 'unlockable' => ($time + 200) <= time()
+ 'unlockable' => ($time + 60) <= time()
];
}
@@ -144,7 +144,10 @@ public function remove(): bool
// check if lock was set by another user
if ($this->data['lock']['user'] !== $this->user()->id()) {
- throw new LogicException('The content lock can only be removed by the user who created it. Use unlock instead.', 409);
+ throw new LogicException([
+ 'fallback' => 'The content lock can only be removed by the user who created it. Use unlock instead.',
+ 'httpCode' => 409
+ ]);
}
// remove lock
diff --git a/src/Cms/ContentLocks.php b/src/Cms/ContentLocks.php
index 2c4c3eea7c..2e4e73a2fb 100644
--- a/src/Cms/ContentLocks.php
+++ b/src/Cms/ContentLocks.php
@@ -121,7 +121,7 @@ public function get(ModelWithContent $model): array
* Returns the file handle to a `.lock` file
*
* @param string $file
- * @param boolean $create Whether to create the file if it does not exist
+ * @param bool $create Whether to create the file if it does not exist
* @return resource|null File handle
*/
protected function handle(string $file, bool $create = false)
@@ -167,7 +167,7 @@ public static function id(ModelWithContent $model): string
*
* @param \Kirby\Cms\ModelWithContent $model
* @param array $data
- * @return boolean
+ * @return bool
*/
public function set(ModelWithContent $model, array $data): bool
{
diff --git a/src/Cms/ContentTranslation.php b/src/Cms/ContentTranslation.php
index 3bc478694b..e51bfc040c 100644
--- a/src/Cms/ContentTranslation.php
+++ b/src/Cms/ContentTranslation.php
@@ -119,7 +119,7 @@ public function contentFile(): string
/**
* Checks if the translation file exists
*
- * @return boolean
+ * @return bool
*/
public function exists(): bool
{
@@ -140,7 +140,7 @@ public function id(): string
* Checks if the this is the default translation
* of the model
*
- * @return boolean
+ * @return bool
*/
public function isDefault(): bool
{
diff --git a/src/Cms/Dir.php b/src/Cms/Dir.php
index 434c4941d4..efcd3bd7eb 100644
--- a/src/Cms/Dir.php
+++ b/src/Cms/Dir.php
@@ -27,7 +27,7 @@ class Dir extends \Kirby\Toolkit\Dir
* @param string $dir
* @param string $contentExtension
* @param array $contentIgnore
- * @param boolean $multilang
+ * @param bool $multilang
* @return array
*/
public static function inventory(string $dir, string $contentExtension = 'txt', array $contentIgnore = null, bool $multilang = false): array
diff --git a/src/Cms/Field.php b/src/Cms/Field.php
index 02e8747de2..5ce8e7be89 100644
--- a/src/Cms/Field.php
+++ b/src/Cms/Field.php
@@ -95,7 +95,7 @@ public function __call(string $method, array $arguments = [])
*
* @param object $parent
* @param string $key
- * @param mixed $value
+ * @param mixed $value
*/
public function __construct($parent = null, string $key, $value)
{
@@ -130,7 +130,7 @@ public function __toString(): string
/**
* Checks if the field exists in the content data array
*
- * @return boolean
+ * @return bool
*/
public function exists(): bool
{
@@ -140,7 +140,7 @@ public function exists(): bool
/**
* Checks if the field content is empty
*
- * @return boolean
+ * @return bool
*/
public function isEmpty(): bool
{
@@ -150,7 +150,7 @@ public function isEmpty(): bool
/**
* Checks if the field content is not empty
*
- * @return boolean
+ * @return bool
*/
public function isNotEmpty(): bool
{
@@ -232,7 +232,7 @@ public function toString(): string
* the modified field will be returned. Otherwise it
* will return the field value.
*
- * @param string|Closure $value
+ * @param string|Closure $value
* @return mixed
*/
public function value($value = null)
diff --git a/src/Cms/File.php b/src/Cms/File.php
index 50bdd73dd0..6e3e41d101 100644
--- a/src/Cms/File.php
+++ b/src/Cms/File.php
@@ -231,12 +231,14 @@ public function contentFileName(): string
* gets dragged onto a textarea
*
* @internal
- * @param string $type (auto|kirbytext|markdown)
+ * @param string $type (null|auto|kirbytext|markdown)
* @param bool $absolute
* @return string
*/
- public function dragText($type = 'auto', bool $absolute = false): string
+ public function dragText(string $type = null, bool $absolute = false): string
{
+ $type = $type ?? 'auto';
+
if ($type === 'auto') {
$type = option('panel.kirbytext', true) ? 'kirbytext' : 'markdown';
}
@@ -363,14 +365,16 @@ public function mediaUrl(): string
*/
public function meta()
{
+ deprecated('$file->meta() is deprecated, use $file->content() instead. $file->meta() will be removed in Kirby 3.5.0.');
+
return $this->content();
}
/**
* Get the file's last modification time.
*
- * @param string $format
- * @param string|null $handler date or strftime
+ * @param string $format
+ * @param string|null $handler date or strftime
* @return mixed
*/
public function modified(string $format = null, string $handler = null)
@@ -392,7 +396,7 @@ public function modified(string $format = null, string $handler = null)
* Timestamp of the last modification
* of the content file
*
- * @return integer
+ * @return int
*/
protected function modifiedContent(): int
{
@@ -403,7 +407,7 @@ protected function modifiedContent(): int
* Timestamp of the last modification
* of the source file
*
- * @return integer
+ * @return int
*/
protected function modifiedFile(): int
{
diff --git a/src/Cms/FileActions.php b/src/Cms/FileActions.php
index 4aef8cfc00..bcbe373365 100644
--- a/src/Cms/FileActions.php
+++ b/src/Cms/FileActions.php
@@ -82,7 +82,7 @@ public function changeName(string $name, bool $sanitize = true)
/**
* Changes the file's sorting number in the meta file
*
- * @param integer $sort
+ * @param int $sort
* @return self
*/
public function changeSort(int $sort)
@@ -256,6 +256,8 @@ public function publish()
*/
public function rename(string $name, bool $sanitize = true)
{
+ deprecated('$file->rename() is deprecated, use $file->changeName() instead. $file->rename() will be removed in Kirby 3.5.0.');
+
return $this->changeName($name, $sanitize);
}
diff --git a/src/Cms/FileBlueprint.php b/src/Cms/FileBlueprint.php
index e570e42fe9..2af1e4ca44 100644
--- a/src/Cms/FileBlueprint.php
+++ b/src/Cms/FileBlueprint.php
@@ -44,7 +44,7 @@ public function accept(): array
}
/**
- * @param mixed $accept
+ * @param mixed $accept
* @return array
*/
protected function normalizeAccept($accept = null): array
diff --git a/src/Cms/FileFoundation.php b/src/Cms/FileFoundation.php
index be70c66112..cc1b4f90fc 100644
--- a/src/Cms/FileFoundation.php
+++ b/src/Cms/FileFoundation.php
@@ -82,7 +82,7 @@ public function asset()
/**
* Checks if the file exists on disk
*
- * @return boolean
+ * @return bool
*/
public function exists(): bool
{
@@ -102,7 +102,7 @@ public function extension(): string
/**
* Converts the file to html
*
- * @param array $attr
+ * @param array $attr
* @return string
*/
public function html(array $attr = []): string
@@ -117,7 +117,7 @@ public function html(array $attr = []): string
/**
* Checks if the file is a resizable image
*
- * @return boolean
+ * @return bool
*/
public function isResizable(): bool
{
@@ -136,7 +136,7 @@ public function isResizable(): bool
* Checks if a preview can be displayed for the file
* in the panel or in the frontend
*
- * @return boolean
+ * @return bool
*/
public function isViewable(): bool
{
@@ -165,8 +165,8 @@ public function kirby()
/**
* Get the file's last modification time.
*
- * @param string $format
- * @param string|null $handler date or strftime
+ * @param string $format
+ * @param string|null $handler date or strftime
* @return mixed
*/
public function modified(string $format = null, string $handler = null)
diff --git a/src/Cms/FileModifications.php b/src/Cms/FileModifications.php
index 2a50ce2ebf..00b0bba36d 100644
--- a/src/Cms/FileModifications.php
+++ b/src/Cms/FileModifications.php
@@ -18,7 +18,7 @@ trait FileModifications
/**
* Blurs the image by the given amount of pixels
*
- * @param boolean $pixels
+ * @param bool $pixels
* @return \Kirby\Cms\FileVersion|\Kirby\Cms\File
*/
public function blur($pixels = true)
@@ -39,8 +39,8 @@ public function bw()
/**
* Crops the image by the given width and height
*
- * @param integer $width
- * @param integer $height
+ * @param int $width
+ * @param int $height
* @param string|array $options
* @return \Kirby\Cms\FileVersion|\Kirby\Cms\File
*/
@@ -71,7 +71,7 @@ public function crop(int $width, int $height = null, $options = null)
/**
* Sets the JPEG compression quality
*
- * @param integer $quality
+ * @param int $quality
* @return \Kirby\Cms\FileVersion|\Kirby\Cms\File
*/
public function quality(int $quality)
@@ -83,9 +83,9 @@ public function quality(int $quality)
* Resizes the file with the given width and height
* while keeping the aspect ratio.
*
- * @param integer $width
- * @param integer $height
- * @param integer $quality
+ * @param int $width
+ * @param int $height
+ * @param int $quality
* @return \Kirby\Cms\FileVersion|\Kirby\Cms\File
*/
public function resize(int $width = null, int $height = null, int $quality = null)
diff --git a/src/Cms/FilePicker.php b/src/Cms/FilePicker.php
new file mode 100644
index 0000000000..b09c09f75c
--- /dev/null
+++ b/src/Cms/FilePicker.php
@@ -0,0 +1,73 @@
+
+ * @link https://getkirby.com
+ * @copyright Bastian Allgeier GmbH
+ * @license https://getkirby.com/license
+ */
+class FilePicker extends Picker
+{
+ /**
+ * Extends the basic defaults
+ *
+ * @return array
+ */
+ public function defaults(): array
+ {
+ $defaults = parent::defaults();
+ $defaults['text'] = '{{ file.filename }}';
+
+ return $defaults;
+ }
+
+ /**
+ * Search all files for the picker
+ *
+ * @return \Kirby\Cms\Files|null
+ */
+ public function items()
+ {
+ $model = $this->options['model'];
+
+ // find the right default query
+ if (empty($this->options['query']) === false) {
+ $query = $this->options['query'];
+ } elseif (is_a($model, 'Kirby\Cms\File') === true) {
+ $query = 'file.siblings';
+ } else {
+ $query = $model::CLASS_ALIAS . '.files';
+ }
+
+ // fetch all files for the picker
+ $files = $model->query($query);
+
+ // help mitigate some typical query usage issues
+ // by converting site and page objects to proper
+ // pages by returning their children
+ if (is_a($files, 'Kirby\Cms\Site') === true) {
+ $files = $files->files();
+ } elseif (is_a($files, 'Kirby\Cms\Page') === true) {
+ $files = $files->files();
+ } elseif (is_a($files, 'Kirby\Cms\User') === true) {
+ $files = $files->files();
+ } elseif (is_a($files, 'Kirby\Cms\Files') === false) {
+ throw new InvalidArgumentException('Your query must return a set of files');
+ }
+
+ // search
+ $files = $this->search($files);
+
+ // paginate
+ return $this->paginate($files);
+ }
+}
diff --git a/src/Cms/Filename.php b/src/Cms/Filename.php
index a34c110ce4..d4fa70814d 100644
--- a/src/Cms/Filename.php
+++ b/src/Cms/Filename.php
@@ -68,7 +68,7 @@ class Filename
*
* @param string $filename
* @param string $template
- * @param array $attributes
+ * @param array $attributes
*/
public function __construct(string $filename, string $template, array $attributes = [])
{
@@ -118,7 +118,7 @@ public function attributesToArray(): array
* to a string, that can be used in the
* new filename
*
- * @param string $prefix The prefix will be used in the filename creation
+ * @param string $prefix The prefix will be used in the filename creation
* @return string
*/
public function attributesToString(string $prefix = null): string
@@ -265,7 +265,7 @@ public function quality()
* to lowercase and `jpeg` will be
* replaced with `jpg`
*
- * @param string $extension
+ * @param string $extension
* @return string
*/
protected function sanitizeExtension(string $extension): string
@@ -279,7 +279,7 @@ protected function sanitizeExtension(string $extension): string
* Sanitizes the name with Kirby's
* Str::slug function
*
- * @param string $name
+ * @param string $name
* @return string
*/
protected function sanitizeName(string $name): string
diff --git a/src/Cms/HasChildren.php b/src/Cms/HasChildren.php
index 0e01be5766..dbdb74f876 100644
--- a/src/Cms/HasChildren.php
+++ b/src/Cms/HasChildren.php
@@ -157,7 +157,7 @@ public function grandChildren()
/**
* Checks if the model has any children
*
- * @return boolean
+ * @return bool
*/
public function hasChildren(): bool
{
@@ -167,7 +167,7 @@ public function hasChildren(): bool
/**
* Checks if the model has any drafts
*
- * @return boolean
+ * @return bool
*/
public function hasDrafts(): bool
{
@@ -175,18 +175,20 @@ public function hasDrafts(): bool
}
/**
- * @deprecated 3.0.0 Use `Page::hasUnlistedChildren` instead
- * @return boolean
+ * @deprecated 3.0.0 Use `Page::hasUnlistedChildren()` instead
+ * @return bool
*/
public function hasInvisibleChildren(): bool
{
+ deprecated('$page->hasInvisibleChildren() is deprecated, use $page->hasUnlistedChildren() instead. $page->hasInvisibleChildren() will be removed in Kirby 3.5.0.');
+
return $this->hasUnlistedChildren();
}
/**
* Checks if the page has any listed children
*
- * @return boolean
+ * @return bool
*/
public function hasListedChildren(): bool
{
@@ -196,7 +198,7 @@ public function hasListedChildren(): bool
/**
* Checks if the page has any unlisted children
*
- * @return boolean
+ * @return bool
*/
public function hasUnlistedChildren(): bool
{
@@ -204,11 +206,13 @@ public function hasUnlistedChildren(): bool
}
/**
- * @deprecated 3.0.0 Use `Page::hasListedChildren` instead
- * @return boolean
+ * @deprecated 3.0.0 Use `Page::hasListedChildren()` instead
+ * @return bool
*/
public function hasVisibleChildren(): bool
{
+ deprecated('$page->hasVisibleChildren() is deprecated, use $page->hasListedChildren() instead. $page->hasVisibleChildren() will be removed in Kirby 3.5.0.');
+
return $this->hasListedChildren();
}
diff --git a/src/Cms/HasMethods.php b/src/Cms/HasMethods.php
index 9fd7065c86..4a1a6bc963 100644
--- a/src/Cms/HasMethods.php
+++ b/src/Cms/HasMethods.php
@@ -25,8 +25,8 @@ trait HasMethods
* passed arguments
*
* @internal
- * @param string $method
- * @param array $args
+ * @param string $method
+ * @param array $args
* @return mixed
*/
public function callMethod(string $method, array $args = [])
@@ -39,7 +39,7 @@ public function callMethod(string $method, array $args = [])
*
* @internal
* @param string $method
- * @return boolean
+ * @return bool
*/
public function hasMethod(string $method): bool
{
diff --git a/src/Cms/Language.php b/src/Cms/Language.php
index a5f96a8de1..1404524c12 100644
--- a/src/Cms/Language.php
+++ b/src/Cms/Language.php
@@ -58,6 +58,11 @@ class Language extends Model
*/
protected $slugs;
+ /**
+ * @var array|null
+ */
+ protected $smartypants;
+
/**
* @var array|null
*/
@@ -85,6 +90,7 @@ public function __construct(array $props)
'locale',
'name',
'slugs',
+ 'smartypants',
'translations',
'url',
]);
@@ -111,6 +117,28 @@ public function __toString(): string
return $this->code();
}
+ /**
+ * Returns the base Url for the language
+ * without the path or other cruft
+ *
+ * @return string
+ */
+ public function baseUrl(): string
+ {
+ $kirbyUrl = $this->kirby()->url();
+ $languageUrl = $this->url();
+
+ if (empty($this->url)) {
+ return $kirbyUrl;
+ }
+
+ if (Str::startsWith($languageUrl, $kirbyUrl) === true) {
+ return $kirbyUrl;
+ }
+
+ return Url::base($languageUrl) ?? $kirbyUrl;
+ }
+
/**
* Returns the language code/id.
* The language code is used in
@@ -129,7 +157,7 @@ public function code(): string
*
* @param string $from
* @param string $to
- * @return boolean
+ * @return bool
*/
protected static function converter(string $from, string $to): bool
{
@@ -201,7 +229,7 @@ public static function create(array $props)
* all its translation files
*
* @internal
- * @return boolean
+ * @return bool
*/
public function delete(): bool
{
@@ -270,7 +298,7 @@ public function direction(): string
/**
* Check if the language file exists
*
- * @return boolean
+ * @return bool
*/
public function exists(): bool
{
@@ -281,7 +309,7 @@ public function exists(): bool
* Checks if this is the default language
* for the site.
*
- * @return boolean
+ * @return bool
*/
public function isDefault(): bool
{
@@ -325,6 +353,20 @@ public function name(): string
return $this->name;
}
+ /**
+ * Returns the URL path for the language
+ *
+ * @return string
+ */
+ public function path(): string
+ {
+ if ($this->url === null) {
+ return $this->code;
+ }
+
+ return Url::path($this->url());
+ }
+
/**
* Returns the routing pattern for the language
*
@@ -332,11 +374,13 @@ public function name(): string
*/
public function pattern(): string
{
- if (empty($this->url) === true) {
- return $this->code;
+ $path = $this->path();
+
+ if (empty($path) === true) {
+ return '(:all)';
}
- return trim($this->url, '/');
+ return $path . '/(:all?)';
}
/**
@@ -430,7 +474,7 @@ protected function setCode(string $code)
}
/**
- * @param boolean $default
+ * @param bool $default
* @return self
*/
protected function setDefault(bool $default = false)
@@ -488,6 +532,16 @@ protected function setSlugs(array $slugs = null)
return $this;
}
+ /**
+ * @param array $smartypants
+ * @return self
+ */
+ protected function setSmartypants(array $smartypants = null)
+ {
+ $this->smartypants = $smartypants ?? [];
+ return $this;
+ }
+
/**
* @param array $translations
* @return self
@@ -518,6 +572,16 @@ public function slugs(): array
return $this->slugs;
}
+ /**
+ * Returns the custom SmartyPants options for this language
+ *
+ * @return array
+ */
+ public function smartypants(): array
+ {
+ return $this->smartypants;
+ }
+
/**
* Returns the most important
* properties as array
@@ -554,7 +618,13 @@ public function translations(): array
*/
public function url(): string
{
- return Url::makeAbsolute($this->pattern(), $this->kirby()->url());
+ $url = $this->url;
+
+ if ($url === null) {
+ $url = '/' . $this->code;
+ }
+
+ return Url::makeAbsolute($url, $this->kirby()->url());
}
/**
diff --git a/src/Cms/LanguageRoutes.php b/src/Cms/LanguageRoutes.php
new file mode 100644
index 0000000000..7d4e3ee114
--- /dev/null
+++ b/src/Cms/LanguageRoutes.php
@@ -0,0 +1,143 @@
+url();
+
+ foreach ($kirby->languages() as $language) {
+
+ // ignore languages with a different base url
+ if ($language->baseurl() !== $baseurl) {
+ continue;
+ }
+
+ $routes[] = [
+ 'pattern' => $language->pattern(),
+ 'method' => 'ALL',
+ 'env' => 'site',
+ 'action' => function ($path = null) use ($language) {
+ if ($result = $language->router()->call($path)) {
+ return $result;
+ }
+
+ // jump through to the fallback if nothing
+ // can be found for this language
+ $this->next();
+ }
+ ];
+ }
+
+ $routes[] = static::fallback($kirby);
+
+ return $routes;
+ }
+
+
+ /**
+ * Create the fallback route
+ * for unprefixed default language URLs.
+ *
+ * @param \Kirby\Cms\App $kirby
+ * @return array
+ */
+ public static function fallback(App $kirby): array
+ {
+ return [
+ 'pattern' => '(:all)',
+ 'method' => 'ALL',
+ 'env' => 'site',
+ 'action' => function (string $path) use ($kirby) {
+
+ // check for content representations or files
+ $extension = F::extension($path);
+
+ // try to redirect prefixed pages
+ if (empty($extension) === true && $page = $kirby->page($path)) {
+ $url = $kirby->request()->url([
+ 'query' => null,
+ 'params' => null,
+ 'fragment' => null
+ ]);
+
+ if ($url->toString() !== $page->url()) {
+ return $kirby
+ ->response()
+ ->redirect($page->url());
+ }
+ }
+
+ return $kirby->defaultLanguage()->router()->call($path);
+ }
+ ];
+ }
+
+ /**
+ * Create the multi-language home page route
+ *
+ * @param \Kirby\Cms\App $kirby
+ * @return array
+ */
+ public static function home(App $kirby): array
+ {
+ // Multi-language home
+ return [
+ 'pattern' => '',
+ 'method' => 'ALL',
+ 'env' => 'site',
+ 'action' => function () use ($kirby) {
+
+ // find all languages with the same base url as the current installation
+ $languages = $kirby->languages()->filterBy('baseurl', $kirby->url());
+
+ // if there's no language with a matching base url,
+ // redirect to the default language
+ if ($languages->count() === 0) {
+ return $kirby
+ ->response()
+ ->redirect($kirby->defaultLanguage()->url());
+ }
+
+ // if there's just one language, we take that to render the home page
+ if ($languages->count() === 1) {
+ $currentLanguage = $languages->first();
+ } else {
+ $currentLanguage = $kirby->defaultLanguage();
+ }
+
+ // language detection on the home page with / as URL
+ if ($kirby->url() !== $currentLanguage->url()) {
+ if ($kirby->option('languages.detect') === true) {
+ return $kirby
+ ->response()
+ ->redirect($kirby->detectedLanguage()->url());
+ }
+
+ return $kirby
+ ->response()
+ ->redirect($currentLanguage->url());
+ }
+
+ // render the home page of the current language
+ return $currentLanguage->router()->call();
+ }
+ ];
+ }
+}
diff --git a/src/Cms/Languages.php b/src/Cms/Languages.php
index 0ca08fc5ed..e2167da600 100644
--- a/src/Cms/Languages.php
+++ b/src/Cms/Languages.php
@@ -72,11 +72,13 @@ public function default()
}
/**
- * @deprecated 3.0.0 Use `Languages::default()`instead
+ * @deprecated 3.0.0 Use `Languages::default()` instead
* @return \Kirby\Cms\Language|null
*/
public function findDefault()
{
+ deprecated('$languages->findDefault() is deprecated, use $languages->default() instead. $languages->findDefault() will be removed in Kirby 3.5.0.');
+
return $this->default();
}
diff --git a/src/Cms/Media.php b/src/Cms/Media.php
index 544749abb4..804ac3ccd1 100644
--- a/src/Cms/Media.php
+++ b/src/Cms/Media.php
@@ -59,7 +59,7 @@ public static function link(Model $model = null, string $hash, string $filename)
*
* @param string $src
* @param string $dest
- * @return boolean
+ * @return bool
*/
public static function publish(string $src, string $dest): bool
{
diff --git a/src/Cms/ModelWithContent.php b/src/Cms/ModelWithContent.php
index 7d342327b8..2c9f8be5ba 100644
--- a/src/Cms/ModelWithContent.php
+++ b/src/Cms/ModelWithContent.php
@@ -19,6 +19,14 @@
*/
abstract class ModelWithContent extends Model
{
+ /**
+ * Each model must define a CLASS_ALIAS
+ * which will be used in template queries.
+ * The CLASS_ALIAS is a short human-readable
+ * version of the class name. I.e. page.
+ */
+ const CLASS_ALIAS = null;
+
/**
* The content
*
@@ -194,8 +202,8 @@ abstract public function contentFileName(): string;
* Decrement a given field value
*
* @param string $field
- * @param integer $by
- * @param integer $min
+ * @param int $by
+ * @param int $min
* @return self
*/
public function decrement(string $field, int $by = 1, int $min = 0)
@@ -231,8 +239,8 @@ public function errors(): array
* Increment a given field value
*
* @param string $field
- * @param integer $by
- * @param integer $max
+ * @param int $by
+ * @param int $max
* @return self
*/
public function increment(string $field, int $by = 1, int $max = null)
@@ -246,10 +254,21 @@ public function increment(string $field, int $by = 1, int $max = null)
return $this->update([$field => $value]);
}
+ /**
+ * Checks if the model is locked for the current user
+ *
+ * @return bool
+ */
+ public function isLocked(): bool
+ {
+ $lock = $this->lock();
+ return $lock && $lock->isLocked() === true;
+ }
+
/**
* Checks if the data has any errors
*
- * @return boolean
+ * @return bool
*/
public function isValid(): bool
{
@@ -382,6 +401,38 @@ protected function panelImageSource(string $query = null)
return $image;
}
+ /**
+ * Returns an array of all actions
+ * that can be performed in the Panel
+ * This also checks for the lock status
+ *
+ * @param array $unlock An array of options that will be force-unlocked
+ * @return array
+ */
+ public function panelOptions(array $unlock = []): array
+ {
+ $options = $this->permissions()->toArray();
+
+ if ($this->isLocked()) {
+ foreach ($options as $key => $value) {
+ if (in_array($key, $unlock)) {
+ continue;
+ }
+
+ $options[$key] = false;
+ }
+ }
+
+ return $options;
+ }
+
+ /**
+ * Must return the permissions object for the model
+ *
+ * @return \Kirby\Cms\ModelPermissions
+ */
+ abstract public function permissions();
+
/**
* Creates a string query, starting from the model
*
@@ -618,7 +669,7 @@ public function translations()
*
* @param array $input
* @param string $languageCode
- * @param boolean $validate
+ * @param bool $validate
* @return self
*/
public function update(array $input = null, string $languageCode = null, bool $validate = false)
@@ -657,7 +708,7 @@ public function update(array $input = null, string $languageCode = null, bool $v
* @internal
* @param array $data
* @param string $languageCode
- * @return boolean
+ * @return bool
*/
public function writeContent(array $data, string $languageCode = null): bool
{
diff --git a/src/Cms/NestCollection.php b/src/Cms/NestCollection.php
index e3bf7c5d2c..2251dcb8cc 100644
--- a/src/Cms/NestCollection.php
+++ b/src/Cms/NestCollection.php
@@ -21,7 +21,7 @@ class NestCollection extends BaseCollection
* to an array. This can also take a callback
* function to further modify the array result.
*
- * @param Closure $map
+ * @param Closure $map
* @return array
*/
public function toArray(Closure $map = null): array
diff --git a/src/Cms/Page.php b/src/Cms/Page.php
index c6dc55a7f0..77aa8537db 100644
--- a/src/Cms/Page.php
+++ b/src/Cms/Page.php
@@ -104,7 +104,7 @@ class Page extends ModelWithContent
/**
* The sorting number
*
- * @var integer|null
+ * @var int|null
*/
protected $num;
@@ -253,15 +253,14 @@ public function blueprints(string $inSection = null): array
$templates = [];
}
- // add the current template to the array
- $templates[] = $currentTemplate;
+ // add the current template to the array if it's not already there
+ if (in_array($currentTemplate, $templates) === false) {
+ array_unshift($templates, $currentTemplate);
+ }
// make sure every template is only included once
$templates = array_unique($templates);
- // sort the templates
- asort($templates);
-
foreach ($templates as $template) {
try {
$props = Blueprint::load('pages/' . $template);
@@ -352,7 +351,7 @@ public function controller($data = [], $contentType = 'html'): array
* Returns a number indicating how deep the page
* is nested within the content folder
*
- * @return integer
+ * @return int
*/
public function depth(): int
{
@@ -408,11 +407,13 @@ public function diruri(): string
* gets dragged onto a textarea
*
* @internal
- * @param string $type (auto|kirbytext|markdown)
+ * @param string $type (null|auto|kirbytext|markdown)
* @return string
*/
- public function dragText(string $type = 'auto'): string
+ public function dragText(string $type = null): string
{
+ $type = $type ?? 'auto';
+
if ($type === 'auto') {
$type = option('panel.kirbytext', true) ? 'kirbytext' : 'markdown';
}
@@ -456,7 +457,7 @@ public static function factory($props)
* Checks if the intended template
* for the page exists.
*
- * @return boolean
+ * @return bool
*/
public function hasTemplate(): bool
{
@@ -563,7 +564,7 @@ public function isActive(): bool
* Checks if the page is a direct or indirect ancestor of the given $page object
*
* @param Page $child
- * @return boolean
+ * @return bool
*/
public function isAncestorOf(Page $child): bool
{
@@ -575,7 +576,7 @@ public function isAncestorOf(Page $child): bool
* pages cache. This will also check if one
* of the ignore rules from the config kick in.
*
- * @return boolean
+ * @return bool
*/
public function isCacheable(): bool
{
@@ -628,12 +629,12 @@ public function isCacheable(): bool
* Checks if the page is a child of the given page
*
* @param \Kirby\Cms\Page|string $parent
- * @return boolean
+ * @return bool
*/
public function isChildOf($parent): bool
{
- if ($parent = $this->parent()) {
- return $parent->is($parent);
+ if ($parentObj = $this->parent()) {
+ return $parentObj->is($parent);
}
return false;
@@ -643,7 +644,7 @@ public function isChildOf($parent): bool
* Checks if the page is a descendant of the given page
*
* @param \Kirby\Cms\Page|string $parent
- * @return boolean
+ * @return bool
*/
public function isDescendantOf($parent): bool
{
@@ -661,7 +662,7 @@ public function isDescendantOf($parent): bool
/**
* Checks if the page is a descendant of the currently active page
*
- * @return boolean
+ * @return bool
*/
public function isDescendantOfActive(): bool
{
@@ -675,7 +676,7 @@ public function isDescendantOfActive(): bool
/**
* Checks if the current page is a draft
*
- * @return boolean
+ * @return bool
*/
public function isDraft(): bool
{
@@ -695,7 +696,7 @@ public function isErrorPage(): bool
/**
* Check if the page can be read by the current user
*
- * @return boolean
+ * @return bool
*/
public function isReadable(): bool
{
@@ -725,7 +726,7 @@ public function isHomePage(): bool
* home and error page to stop certain
* actions. That's why there's a shortcut.
*
- * @return boolean
+ * @return bool
*/
public function isHomeOrErrorPage(): bool
{
@@ -733,18 +734,20 @@ public function isHomeOrErrorPage(): bool
}
/**
- * @deprecated 3.0.0 Use `Page::isUnlisted()` intead
+ * @deprecated 3.0.0 Use `Page::isUnlisted()` instead
* @return bool
*/
public function isInvisible(): bool
{
+ deprecated('$page->isInvisible() is deprecated, use $page->isUnlisted() instead. $page->isInvisible() will be removed in Kirby 3.5.0.');
+
return $this->isUnlisted();
}
/**
* Checks if the page has a sorting number
*
- * @return boolean
+ * @return bool
*/
public function isListed(): bool
{
@@ -776,7 +779,7 @@ public function isOpen(): bool
/**
* Checks if the page is sortable
*
- * @return boolean
+ * @return bool
*/
public function isSortable(): bool
{
@@ -786,7 +789,7 @@ public function isSortable(): bool
/**
* Checks if the page has no sorting number
*
- * @return boolean
+ * @return bool
*/
public function isUnlisted(): bool
{
@@ -794,11 +797,13 @@ public function isUnlisted(): bool
}
/**
- * @deprecated 3.0.0 Use `Page::isListed()` intead
+ * @deprecated 3.0.0 Use `Page::isListed()` instead
* @return bool
*/
public function isVisible(): bool
{
+ deprecated('$page->isVisible() is deprecated, use $page->isListed() instead. $page->isVisible() will be removed in Kirby 3.5.0.');
+
return $this->isListed();
}
@@ -808,7 +813,7 @@ public function isVisible(): bool
*
* @internal
* @param string $token
- * @return boolean
+ * @return bool
*/
public function isVerified(string $token = null)
{
@@ -884,7 +889,7 @@ public function modified(string $format = null, string $handler = null)
/**
* Returns the sorting number
*
- * @return integer|null
+ * @return int|null
*/
public function num(): ?int
{
@@ -1099,7 +1104,7 @@ public function previewUrl(): ?string
*
* @param array $data
* @param string $contentType
- * @param integer $code
+ * @param int $code
* @return string
*/
public function render(array $data = [], $contentType = 'html'): string
@@ -1241,7 +1246,7 @@ protected function setDirname(string $dirname = null)
/**
* Sets the draft flag
*
- * @param boolean $isDraft
+ * @param bool $isDraft
* @return self
*/
protected function setIsDraft(bool $isDraft = null)
@@ -1253,7 +1258,7 @@ protected function setIsDraft(bool $isDraft = null)
/**
* Sets the sorting number
*
- * @param integer $num
+ * @param int $num
* @return self
*/
protected function setNum(int $num = null)
diff --git a/src/Cms/PageActions.php b/src/Cms/PageActions.php
index d180c461a5..b26f01dc14 100644
--- a/src/Cms/PageActions.php
+++ b/src/Cms/PageActions.php
@@ -160,7 +160,7 @@ protected function changeSlugForLanguage(string $slug, string $languageCode = nu
* to either draft, listed or unlisted
*
* @param string $status "draft", "listed" or "unlisted"
- * @param integer $position Optional sorting number
+ * @param int $position Optional sorting number
* @return self
*/
public function changeStatus(string $status, int $position = null)
@@ -462,8 +462,8 @@ public function createChild(array $props)
* Create the sorting number for the page
* depending on the blueprint settings
*
- * @param integer $num
- * @return integer
+ * @param int $num
+ * @return int
*/
public function createNum(int $num = null): int
{
@@ -631,12 +631,13 @@ public function publish()
*/
public function purge()
{
- $this->children = null;
- $this->blueprint = null;
- $this->drafts = null;
- $this->files = null;
- $this->content = null;
- $this->inventory = null;
+ $this->blueprint = null;
+ $this->children = null;
+ $this->content = null;
+ $this->drafts = null;
+ $this->files = null;
+ $this->inventory = null;
+ $this->translations = null;
return $this;
}
@@ -756,7 +757,7 @@ public function unpublish()
*
* @param array $input
* @param string $language
- * @param boolean $validate
+ * @param bool $validate
* @return self
*/
public function update(array $input = null, string $language = null, bool $validate = false)
diff --git a/src/Cms/PageBlueprint.php b/src/Cms/PageBlueprint.php
index 7256bc51f0..3771e4b7d2 100644
--- a/src/Cms/PageBlueprint.php
+++ b/src/Cms/PageBlueprint.php
@@ -75,7 +75,6 @@ public function num(): string
protected function normalizeNum($num): string
{
$aliases = [
- 0 => 'zero',
'0' => 'zero',
'sort' => 'default',
];
@@ -185,7 +184,7 @@ public function options(): array
* button in the panel and redirects it to a
* different URL if necessary.
*
- * @return string|boolean
+ * @return string|bool
*/
public function preview()
{
diff --git a/src/Cms/PagePicker.php b/src/Cms/PagePicker.php
new file mode 100644
index 0000000000..e8529acbf8
--- /dev/null
+++ b/src/Cms/PagePicker.php
@@ -0,0 +1,264 @@
+
+ * @link https://getkirby.com
+ * @copyright Bastian Allgeier GmbH
+ * @license https://getkirby.com/license
+ */
+class PagePicker extends Picker
+{
+ /**
+ * @var \Kirby\Cms\Pages
+ */
+ protected $items;
+
+ /**
+ * @var \Kirby\Cms\Pages
+ */
+ protected $itemsForQuery;
+
+ /**
+ * @var \Kirby\Cms\Page|\Kirby\Cms\Site|null
+ */
+ protected $parent;
+
+ /**
+ * Extends the basic defaults
+ *
+ * @return array
+ */
+ public function defaults(): array
+ {
+ return array_merge(parent::defaults(), [
+ // Page ID of the selected parent. Used to navigate
+ 'parent' => null,
+ // enable/disable subpage navigation
+ 'subpages' => true,
+ ]);
+ }
+
+ /**
+ * Returns the parent model object that
+ * is currently selected in the page picker.
+ * It normally starts at the site, but can
+ * also be any subpage. When a query is given
+ * and subpage navigation is deactivated,
+ * there will be no model available at all.
+ *
+ * @return \Kirby\Cms\Page|\Kirby\Cms\Site|null
+ */
+ public function model()
+ {
+ // no subpages navigation = no model
+ if ($this->options['subpages'] === false) {
+ return null;
+ }
+
+ // the model for queries is a bit more tricky to find
+ if (empty($this->options['query']) === false) {
+ return $this->modelForQuery();
+ }
+
+ return $this->parent();
+ }
+
+ /**
+ * Returns a model object for the given
+ * query, depending on the parent and subpages
+ * options.
+ *
+ * @return \Kirby\Cms\Page|\Kirby\Cms\Site|null
+ */
+ public function modelForQuery()
+ {
+ if ($this->options['subpages'] === true && empty($this->options['parent']) === false) {
+ return $this->parent();
+ }
+
+ if ($items = $this->items()) {
+ return $items->parent();
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns basic information about the
+ * parent model that is currently selected
+ * in the page picker.
+ *
+ * @param \Kirby\Cms\Site|\Kirby\Cms\Page|null
+ * @return array|null
+ */
+ public function modelToArray($model = null): ?array
+ {
+ if ($model === null) {
+ return null;
+ }
+
+ // the selected model is the site. there's nothing above
+ if (is_a($model, 'Kirby\Cms\Site') === true) {
+ return [
+ 'id' => null,
+ 'parent' => null,
+ 'title' => $model->title()->value()
+ ];
+ }
+
+ // the top-most page has been reached
+ // the missing id indicates that there's nothing above
+ if ($model->id() === $this->start()->id()) {
+ return [
+ 'id' => null,
+ 'parent' => null,
+ 'title' => $model->title()->value()
+ ];
+ }
+
+ // the model is a regular page
+ return [
+ 'id' => $model->id(),
+ 'parent' => $model->parentModel()->id(),
+ 'title' => $model->title()->value()
+ ];
+ }
+
+ /**
+ * Search all pages for the picker
+ *
+ * @return \Kirby\Cms\Pages|null
+ */
+ public function items()
+ {
+ // cache
+ if ($this->items !== null) {
+ return $this->items;
+ }
+
+ // no query? simple parent-based search for pages
+ if (empty($this->options['query']) === true) {
+ $items = $this->itemsForParent();
+
+ // when subpage navigation is enabled, a parent
+ // might be passed in addition to the query.
+ // The parent then takes priority.
+ } elseif ($this->options['subpages'] === true && empty($this->options['parent']) === false) {
+ $items = $this->itemsForParent();
+
+ // search by query
+ } else {
+ $items = $this->itemsForQuery();
+ }
+
+ // filter protected pages
+ $items = $items->filterBy('isReadable', true);
+
+ // search
+ $items = $this->search($items);
+
+ // paginate the result
+ return $this->items = $this->paginate($items);
+ }
+
+ /**
+ * Search for pages by parent
+ *
+ * @return \Kirby\Cms\Pages
+ */
+ public function itemsForParent()
+ {
+ return $this->parent()->children();
+ }
+
+ /**
+ * Search for pages by query string
+ *
+ * @return \Kirby\Cms\Pages
+ */
+ public function itemsForQuery()
+ {
+ // cache
+ if ($this->itemsForQuery !== null) {
+ return $this->itemsForQuery;
+ }
+
+ $model = $this->options['model'];
+ $items = $model->query($this->options['query']);
+
+ // help mitigate some typical query usage issues
+ // by converting site and page objects to proper
+ // pages by returning their children
+ if (is_a($items, 'Kirby\Cms\Site') === true) {
+ $items = $items->children();
+ } elseif (is_a($items, 'Kirby\Cms\Page') === true) {
+ $items = $items->children();
+ } elseif (is_a($items, 'Kirby\Cms\Pages') === false) {
+ throw new InvalidArgumentException('Your query must return a set of pages');
+ }
+
+ return $this->itemsForQuery = $items;
+ }
+
+ /**
+ * Returns the parent model.
+ * The model will be used to fetch
+ * subpages unless there's a specific
+ * query to find pages instead.
+ *
+ * @return \Kirby\Cms\Page|\Kirby\Cms\Site
+ */
+ public function parent()
+ {
+ if ($this->parent !== null) {
+ return $this->parent;
+ }
+
+ return $this->parent = $this->kirby->page($this->options['parent']) ?? $this->site;
+ }
+
+ /**
+ * Calculates the top-most model (page or site)
+ * that can be accessed when navigating
+ * through pages.
+ *
+ * @return \Kirby\Cms\Page|\Kirby\Cms\Site
+ */
+ public function start()
+ {
+ if (empty($this->options['query']) === false) {
+ if ($items = $this->itemsForQuery()) {
+ return $items->parent();
+ }
+
+ return $this->site;
+ }
+
+ return $this->site;
+ }
+
+ /**
+ * Returns an associative array
+ * with all information for the picker.
+ * This will be passed directly to the API.
+ *
+ * @return array
+ */
+ public function toArray(): array
+ {
+ $array = parent::toArray();
+ $array['model'] = $this->modelToArray($this->model());
+
+ return $array;
+ }
+}
diff --git a/src/Cms/PageRules.php b/src/Cms/PageRules.php
index cddb093fba..d385237fa4 100644
--- a/src/Cms/PageRules.php
+++ b/src/Cms/PageRules.php
@@ -205,6 +205,12 @@ public static function changeTitle(Page $page, string $title): bool
public static function create(Page $page): bool
{
+ if (Str::length($page->slug()) < 1) {
+ throw new InvalidArgumentException([
+ 'key' => 'page.slug.invalid',
+ ]);
+ }
+
if ($page->exists() === true) {
throw new DuplicateException([
'key' => 'page.draft.duplicate',
diff --git a/src/Cms/PageSiblings.php b/src/Cms/PageSiblings.php
index 16af4c37a6..0aa6a1770c 100644
--- a/src/Cms/PageSiblings.php
+++ b/src/Cms/PageSiblings.php
@@ -14,11 +14,13 @@
trait PageSiblings
{
/**
- * @deprecated 3.0.0 Use `Page::hasNextUnlisted` instead
- * @return boolean
+ * @deprecated 3.0.0 Use `Page::hasNextUnlisted()` instead
+ * @return bool
*/
public function hasNextInvisible(): bool
{
+ deprecated('$page->hasNextInvisible() is deprecated, use $page->hasNextUnlisted() instead. $page->hasNextInvisible() will be removed in Kirby 3.5.0.');
+
return $this->hasNextUnlisted();
}
@@ -45,20 +47,24 @@ public function hasNextUnlisted(): bool
}
/**
- * @deprecated 3.0.0 Use `Page::hasNextListed` instead
- * @return boolean
+ * @deprecated 3.0.0 Use `Page::hasNextListed()` instead
+ * @return bool
*/
public function hasNextVisible(): bool
{
+ deprecated('$page->hasNextVisible() is deprecated, use $page->hasNextListed() instead. $page->hasNextVisible() will be removed in Kirby 3.5.0.');
+
return $this->hasNextListed();
}
/**
- * @deprecated 3.0.0 Use `Page::hasPrevUnlisted` instead
- * @return boolean
+ * @deprecated 3.0.0 Use `Page::hasPrevUnlisted()` instead
+ * @return bool
*/
public function hasPrevInvisible(): bool
{
+ deprecated('$page->hasPrevInvisible() is deprecated, use $page->hasPrevUnlisted() instead. $page->hasPrevInvisible() will be removed in Kirby 3.5.0.');
+
return $this->hasPrevUnlisted();
}
@@ -85,11 +91,13 @@ public function hasPrevUnlisted(): bool
}
/**
- * @deprecated 3.0.0 Use `Page::hasPrevListed instead`
- * @return boolean
+ * @deprecated 3.0.0 Use `Page::hasPrevListed()` instead
+ * @return bool
*/
public function hasPrevVisible(): bool
{
+ deprecated('$page->hasPrevVisible() is deprecated, use $page->hasPrevListed() instead. $page->hasPrevVisible() will be removed in Kirby 3.5.0.');
+
return $this->hasPrevListed();
}
@@ -99,6 +107,8 @@ public function hasPrevVisible(): bool
*/
public function nextInvisible()
{
+ deprecated('$page->nextInvisible() is deprecated, use $page->nextUnlisted() instead. $page->nextInvisible() will be removed in Kirby 3.5.0.');
+
return $this->nextUnlisted();
}
@@ -123,11 +133,13 @@ public function nextUnlisted()
}
/**
- * @deprecated 3.0.0 Use `Page::prevListed()` instead
+ * @deprecated 3.0.0 Use `Page::nextListed()` instead
* @return self|null
*/
public function nextVisible()
{
+ deprecated('$page->nextVisible() is deprecated, use $page->nextListed() instead. $page->nextVisible() will be removed in Kirby 3.5.0.');
+
return $this->nextListed();
}
@@ -137,6 +149,8 @@ public function nextVisible()
*/
public function prevInvisible()
{
+ deprecated('$page->prevInvisible() is deprecated, use $page->prevUnlisted() instead. $page->prevInvisible() will be removed in Kirby 3.5.0.');
+
return $this->prevUnlisted();
}
@@ -166,6 +180,8 @@ public function prevUnlisted()
*/
public function prevVisible()
{
+ deprecated('$page->prevVisible() is deprecated, use $page->prevListed() instead. $page->prevVisible() will be removed in Kirby 3.5.0.');
+
return $this->prevListed();
}
diff --git a/src/Cms/Pages.php b/src/Cms/Pages.php
index 199e52027e..086612f3ab 100644
--- a/src/Cms/Pages.php
+++ b/src/Cms/Pages.php
@@ -2,6 +2,8 @@
namespace Kirby\Cms;
+use Kirby\Exception\InvalidArgumentException;
+
/**
* The `$pages` object refers to a
* collection of pages. The pages in this
@@ -55,6 +57,10 @@ public function add($object)
// add a page object
} elseif (is_a($object, 'Kirby\Cms\Page') === true) {
$this->__set($object->id(), $object);
+
+ // give a useful error message on invalid input
+ } elseif (in_array($object, [null, false, true], true) !== true) {
+ throw new InvalidArgumentException('You must pass a Page object to the Pages collection');
}
return $this;
@@ -344,13 +350,15 @@ public function index(bool $drafts = false)
}
/**
- * Deprecated alias for Pages::unlisted()
+ * @deprecated 3.0.0 Use `Pages::unlisted()` instead
*
* @return self
*/
public function invisible()
{
- return $this->filterBy('isUnlisted', '==', true);
+ deprecated('$pages->invisible() is deprecated, use $pages->unlisted() instead. $pages->invisible() will be removed in Kirby 3.5.0.');
+
+ return $this->unlisted();
}
/**
@@ -428,6 +436,27 @@ public function merge(...$args)
return $this;
}
+ /**
+ * Filter all pages by excluding the given template
+ *
+ * @param string|array $templates
+ * @return \Kirby\Cms\Pages
+ */
+ public function notTemplate($templates)
+ {
+ if (empty($templates) === true) {
+ return $this;
+ }
+
+ if (is_array($templates) === false) {
+ $templates = [$templates];
+ }
+
+ return $this->filter(function ($page) use ($templates) {
+ return !in_array($page->intendedTemplate()->name(), $templates);
+ });
+ }
+
/**
* Returns an array with all page numbers
*
@@ -480,12 +509,14 @@ public function videos()
}
/**
- * Deprecated alias for Pages::listed()
+ * @deprecated 3.0.0 Use `Pages::listed()` instead
*
* @return \Kirby\Cms\Pages
*/
public function visible()
{
- return $this->filterBy('isListed', '==', true);
+ deprecated('$pages->visible() is deprecated, use $pages->listed() instead. $pages->visible() will be removed in Kirby 3.5.0.');
+
+ return $this->listed();
}
}
diff --git a/src/Cms/Pagination.php b/src/Cms/Pagination.php
index 4a9008230a..4f6171b318 100644
--- a/src/Cms/Pagination.php
+++ b/src/Cms/Pagination.php
@@ -81,9 +81,9 @@ public function __construct(array $params = [])
}
if ($params['method'] === 'query') {
- $params['page'] = $params['page'] ?? $params['url']->query()->get($params['variable'], 1);
+ $params['page'] = $params['page'] ?? $params['url']->query()->get($params['variable']);
} else {
- $params['page'] = $params['page'] ?? $params['url']->params()->get($params['variable'], 1);
+ $params['page'] = $params['page'] ?? $params['url']->params()->get($params['variable']);
}
parent::__construct($params);
diff --git a/src/Cms/Panel.php b/src/Cms/Panel.php
index d2eaa0532b..cc3edc28ee 100644
--- a/src/Cms/Panel.php
+++ b/src/Cms/Panel.php
@@ -107,6 +107,7 @@ public static function render(App $kirby)
'pluginCss' => $plugins->url('css'),
'pluginJs' => $plugins->url('js'),
'panelUrl' => $uri->path()->toString(true) . '/',
+ 'nonce' => $kirby->nonce(),
'options' => [
'url' => $url,
'site' => $kirby->url('index'),
diff --git a/src/Cms/Picker.php b/src/Cms/Picker.php
new file mode 100644
index 0000000000..c034a63e5b
--- /dev/null
+++ b/src/Cms/Picker.php
@@ -0,0 +1,176 @@
+
+ * @link https://getkirby.com
+ * @copyright Bastian Allgeier GmbH
+ * @license https://getkirby.com/license
+ */
+abstract class Picker
+{
+ /**
+ * @var \Kirby\Cms\App
+ */
+ protected $kirby;
+
+ /**
+ * @var array
+ */
+ protected $options;
+
+ /**
+ * @var \Kirby\Cms\Site
+ */
+ protected $site;
+
+ /**
+ * Creates a new Picker instance
+ *
+ * @param array $params
+ */
+ public function __construct(array $params = [])
+ {
+ $this->options = array_merge($this->defaults(), $params);
+ $this->kirby = $this->options['model']->kirby();
+ $this->site = $this->kirby->site();
+ }
+
+ /**
+ * Return the array of default values
+ *
+ * @return array
+ */
+ protected function defaults(): array
+ {
+ // default params
+ return [
+ // image settings (ratio, cover, etc.)
+ 'image' => [],
+ // query template for the info field
+ 'info' => false,
+ // number of users displayed per pagination page
+ 'limit' => 20,
+ // optional mapping function for the result array
+ 'map' => null,
+ // the reference model
+ 'model' => site(),
+ // current page when paginating
+ 'page' => 1,
+ // a query string to fetch specific items
+ 'query' => null,
+ // search query
+ 'search' => null,
+ // query template for the text field
+ 'text' => null
+ ];
+ }
+
+ /**
+ * Fetches all items for the picker
+ *
+ * @return \Kirby\Cms\Collection|null
+ */
+ abstract public function items();
+
+ /**
+ * Converts all given items to an associative
+ * array that is already optimized for the
+ * panel picker component.
+ *
+ * @param \Kirby\Cms\Collection|null $items
+ * @return array
+ */
+ public function itemsToArray($items = null): array
+ {
+ if ($items === null) {
+ return [];
+ }
+
+ $result = [];
+
+ foreach ($items as $index => $item) {
+ if (empty($this->options['map']) === false) {
+ $result[] = $this->options['map']($item);
+ } else {
+ $result[] = $item->panelPickerData([
+ 'image' => $this->options['image'],
+ 'info' => $this->options['info'],
+ 'model' => $this->options['model'],
+ 'text' => $this->options['text'],
+ ]);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Apply pagination to the collection
+ * of items according to the options.
+ *
+ * @param \Kirby\Cms\Collection $items
+ * @return \Kirby\Cms\Collection
+ */
+ public function paginate($items)
+ {
+ return $items->paginate([
+ 'limit' => $this->options['limit'],
+ 'page' => $this->options['page']
+ ]);
+ }
+
+ /**
+ * Return the most relevant pagination
+ * info as array
+ *
+ * @param \Kirby\Cms\Pagination $pagination
+ * @return array
+ */
+ public function paginationToArray(Pagination $pagination): array
+ {
+ return [
+ 'limit' => $pagination->limit(),
+ 'page' => $pagination->page(),
+ 'total' => $pagination->total()
+ ];
+ }
+
+ /**
+ * Search through the collection of items
+ * if not deactivate in the options
+ *
+ * @param \Kirby\Cms\Collection $items
+ * @return \Kirby\Cms\Collection
+ */
+ public function search($items)
+ {
+ if (empty($this->options['search']) === false) {
+ return $items->search($this->options['search']);
+ }
+
+ return $items;
+ }
+
+ /**
+ * Returns an associative array
+ * with all information for the picker.
+ * This will be passed directly to the API.
+ *
+ * @return array
+ */
+ public function toArray(): array
+ {
+ $items = $this->items();
+
+ return [
+ 'data' => $this->itemsToArray($items),
+ 'pagination' => $this->paginationToArray($items->pagination()),
+ ];
+ }
+}
diff --git a/src/Cms/Responder.php b/src/Cms/Responder.php
index bcb5896853..0ed5169d70 100644
--- a/src/Cms/Responder.php
+++ b/src/Cms/Responder.php
@@ -19,7 +19,7 @@ class Responder
/**
* HTTP status code
*
- * @var integer
+ * @var int
*/
protected $code = null;
@@ -73,8 +73,8 @@ public function body(string $body = null)
/**
* Setter and getter for the status code
*
- * @param integer $code
- * @return integer|self
+ * @param int $code
+ * @return int|self
*/
public function code(int $code = null)
{
@@ -156,7 +156,7 @@ public function json(array $json = null)
* Shortcut to create a redirect response
*
* @param string|null $location
- * @param integer|null $code
+ * @param int|null $code
* @return self
*/
public function redirect(?string $location = null, ?int $code = null)
diff --git a/src/Cms/Roles.php b/src/Cms/Roles.php
index 8c3b56e471..7cb2d39086 100644
--- a/src/Cms/Roles.php
+++ b/src/Cms/Roles.php
@@ -29,8 +29,8 @@ class Roles extends Collection
*/
public function canBeChanged()
{
- if ($user = App::instance()->user()) {
- return $this->filter(function ($role) use ($user) {
+ if (App::instance()->user()) {
+ return $this->filter(function ($role) {
$newUser = new User([
'email' => 'test@getkirby.com',
'role' => $role->id()
@@ -52,8 +52,8 @@ public function canBeChanged()
*/
public function canBeCreated()
{
- if ($user = App::instance()->user()) {
- return $this->filter(function ($role) use ($user) {
+ if (App::instance()->user()) {
+ return $this->filter(function ($role) {
$newUser = new User([
'email' => 'test@getkirby.com',
'role' => $role->id()
diff --git a/src/Cms/Search.php b/src/Cms/Search.php
index 42e08e2ffa..77d3b4bee0 100644
--- a/src/Cms/Search.php
+++ b/src/Cms/Search.php
@@ -73,6 +73,7 @@ public static function collection(Collection $collection, string $query = null,
$keys[] = 'id';
if (is_a($item, 'Kirby\Cms\User') === true) {
+ $keys[] = 'name';
$keys[] = 'email';
$keys[] = 'role';
} elseif (is_a($item, 'Kirby\Cms\Page') === true) {
diff --git a/src/Cms/Site.php b/src/Cms/Site.php
index 6be57371a1..cf1334cbc0 100644
--- a/src/Cms/Site.php
+++ b/src/Cms/Site.php
@@ -273,7 +273,7 @@ public function errorPageId(): string
/**
* Checks if the site exists on disk
*
- * @return boolean
+ * @return bool
*/
public function exists(): bool
{
@@ -391,7 +391,7 @@ public function modified(string $format = null, string $handler = null)
* prop, the home page will be returned if
* it can be found. (see `Site::homePage()`)
*
- * @param string $path
+ * @param string $path
* @return \Kirby\Cms\Page|null
*/
public function page(string $path = null)
@@ -645,8 +645,8 @@ public function urlForLanguage(string $languageCode = null, array $options = nul
* returns the current page
*
* @internal
- * @param string|\Kirby\Cms\Page $page
- * @param string|null $languageCode
+ * @param string|\Kirby\Cms\Page $page
+ * @param string|null $languageCode
* @return \Kirby\Cms\Page
*/
public function visit($page, string $languageCode = null)
diff --git a/src/Cms/SiteActions.php b/src/Cms/SiteActions.php
index 081441932b..db759cfc7d 100644
--- a/src/Cms/SiteActions.php
+++ b/src/Cms/SiteActions.php
@@ -81,11 +81,12 @@ public function createChild(array $props)
*/
public function purge()
{
- $this->children = null;
- $this->blueprint = null;
- $this->files = null;
- $this->content = null;
- $this->inventory = null;
+ $this->blueprint = null;
+ $this->children = null;
+ $this->content = null;
+ $this->files = null;
+ $this->inventory = null;
+ $this->translations = null;
return $this;
}
diff --git a/src/Cms/SiteBlueprint.php b/src/Cms/SiteBlueprint.php
index a98910d876..72d84be25c 100644
--- a/src/Cms/SiteBlueprint.php
+++ b/src/Cms/SiteBlueprint.php
@@ -45,7 +45,7 @@ public function __construct(array $props)
* button in the panel and redirects it to a
* different URL if necessary.
*
- * @return string|boolean
+ * @return string|bool
*/
public function preview()
{
diff --git a/src/Cms/SiteRules.php b/src/Cms/SiteRules.php
index 2a02220824..8fd1d03212 100644
--- a/src/Cms/SiteRules.php
+++ b/src/Cms/SiteRules.php
@@ -2,7 +2,9 @@
namespace Kirby\Cms;
+use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\PermissionException;
+use Kirby\Toolkit\Str;
/**
* Validators for all site actions
@@ -21,6 +23,10 @@ public static function changeTitle(Site $site, string $title): bool
throw new PermissionException(['key' => 'site.changeTitle.permission']);
}
+ if (Str::length($title) === 0) {
+ throw new InvalidArgumentException(['key' => 'site.changeTitle.empty']);
+ }
+
return true;
}
diff --git a/src/Cms/System.php b/src/Cms/System.php
index ff5f2427c9..5db6087bb9 100644
--- a/src/Cms/System.php
+++ b/src/Cms/System.php
@@ -79,7 +79,7 @@ public function status(): array
/**
* Check for a writable accounts folder
*
- * @return boolean
+ * @return bool
*/
public function accounts(): bool
{
@@ -89,7 +89,7 @@ public function accounts(): bool
/**
* Check for a writable content folder
*
- * @return boolean
+ * @return bool
*/
public function content(): bool
{
@@ -99,7 +99,7 @@ public function content(): bool
/**
* Check for an existing curl extension
*
- * @return boolean
+ * @return bool
*/
public function curl(): bool
{
@@ -165,7 +165,7 @@ public function init()
* option must be explicitly set to true
* to get the installer up and running.
*
- * @return boolean
+ * @return bool
*/
public function isInstallable(): bool
{
@@ -175,7 +175,7 @@ public function isInstallable(): bool
/**
* Check if Kirby is already installed
*
- * @return boolean
+ * @return bool
*/
public function isInstalled(): bool
{
@@ -185,7 +185,7 @@ public function isInstalled(): bool
/**
* Check if this is a local installation
*
- * @return boolean
+ * @return bool
*/
public function isLocal(): bool
{
@@ -218,7 +218,7 @@ public function isLocal(): bool
/**
* Check if all tests pass
*
- * @return boolean
+ * @return bool
*/
public function isOk(): bool
{
@@ -318,7 +318,7 @@ public function license()
/**
* Check for an existing mbstring extension
*
- * @return boolean
+ * @return bool
*/
public function mbString(): bool
{
@@ -328,7 +328,7 @@ public function mbString(): bool
/**
* Check for a writable media folder
*
- * @return boolean
+ * @return bool
*/
public function media(): bool
{
@@ -338,7 +338,7 @@ public function media(): bool
/**
* Check for a valid PHP version
*
- * @return boolean
+ * @return bool
*/
public function php(): bool
{
@@ -352,7 +352,7 @@ public function php(): bool
*
* @param string $license
* @param string $email
- * @return boolean
+ * @return bool
*/
public function register(string $license = null, string $email = null): bool
{
@@ -404,7 +404,7 @@ public function register(string $license = null, string $email = null): bool
/**
* Check for a valid server environment
*
- * @return boolean
+ * @return bool
*/
public function server(): bool
{
@@ -424,7 +424,7 @@ public function server(): bool
/**
* Check for a writable sessions folder
*
- * @return boolean
+ * @return bool
*/
public function sessions(): bool
{
diff --git a/src/Cms/Template.php b/src/Cms/Template.php
index c4b0690c41..b7df18edab 100644
--- a/src/Cms/Template.php
+++ b/src/Cms/Template.php
@@ -74,7 +74,7 @@ public function __toString(): string
/**
* Checks if the template exists
*
- * @return boolean
+ * @return bool
*/
public function exists(): bool
{
@@ -190,7 +190,7 @@ public function type(): string
/**
* Checks if the template uses the default type
*
- * @return boolean
+ * @return bool
*/
public function hasDefaultType(): bool
{
diff --git a/src/Cms/User.php b/src/Cms/User.php
index c28d60a2e3..50b8b56c9a 100644
--- a/src/Cms/User.php
+++ b/src/Cms/User.php
@@ -248,7 +248,7 @@ public function email(): ?string
/**
* Checks if the user exists
*
- * @return boolean
+ * @return bool
*/
public function exists(): bool
{
@@ -342,7 +342,7 @@ public function is(User $user = null): bool
/**
* Checks if this user has the admin role
*
- * @return boolean
+ * @return bool
*/
public function isAdmin(): bool
{
@@ -353,7 +353,7 @@ public function isAdmin(): bool
* Checks if the current user is the virtual
* Kirby user
*
- * @return boolean
+ * @return bool
*/
public function isKirby(): bool
{
@@ -363,7 +363,7 @@ public function isKirby(): bool
/**
* Checks if the current user is this user
*
- * @return boolean
+ * @return bool
*/
public function isLoggedIn(): bool
{
@@ -374,7 +374,7 @@ public function isLoggedIn(): bool
* Checks if the user is the last one
* with the admin role
*
- * @return boolean
+ * @return bool
*/
public function isLastAdmin(): bool
{
@@ -384,7 +384,7 @@ public function isLastAdmin(): bool
/**
* Checks if the user is the last user
*
- * @return boolean
+ * @return bool
*/
public function isLastUser(): bool
{
@@ -426,10 +426,16 @@ public function login(string $password, $session = null): bool
*/
public function loginPasswordless($session = null): void
{
+ $kirby = $this->kirby();
+
$session = $this->sessionFromOptions($session);
+ $kirby->trigger('user.login:before', $this, $session);
+
$session->regenerateToken(); // privilege change
$session->data()->set('user.id', $this->id());
+
+ $kirby->trigger('user.login:after', $this, $session);
}
/**
@@ -440,16 +446,23 @@ public function loginPasswordless($session = null): void
*/
public function logout($session = null): void
{
+ $kirby = $this->kirby();
$session = $this->sessionFromOptions($session);
+ $kirby->trigger('user.logout:before', $this, $session);
+
$session->data()->remove('user.id');
if ($session->data()->get() === []) {
// session is now empty, we might as well destroy it
$session->destroy();
+
+ $kirby->trigger('user.logout:after', $this, null);
} else {
// privilege change
$session->regenerateToken();
+
+ $kirby->trigger('user.logout:after', $this, $session);
}
}
@@ -857,7 +870,7 @@ public function username(): ?string
* Compares the given password with the stored one
*
* @param string $password
- * @return boolean
+ * @return bool
*
* @throws NotFoundException If the user has no password
* @throws InvalidArgumentException If the entered password is not valid
diff --git a/src/Cms/UserActions.php b/src/Cms/UserActions.php
index 97dc0efd90..3f533dbfc6 100644
--- a/src/Cms/UserActions.php
+++ b/src/Cms/UserActions.php
@@ -293,7 +293,7 @@ protected function updateCredentials(array $credentials): bool
* Writes the account information to disk
*
* @param array $credentials
- * @return boolean
+ * @return bool
*/
protected function writeCredentials(array $credentials): bool
{
diff --git a/src/Cms/UserPicker.php b/src/Cms/UserPicker.php
new file mode 100644
index 0000000000..98780dbcbb
--- /dev/null
+++ b/src/Cms/UserPicker.php
@@ -0,0 +1,68 @@
+
+ * @link https://getkirby.com
+ * @copyright Bastian Allgeier GmbH
+ * @license https://getkirby.com/license
+ */
+class UserPicker extends Picker
+{
+ /**
+ * Extends the basic defaults
+ *
+ * @return array
+ */
+ public function defaults(): array
+ {
+ $defaults = parent::defaults();
+ $defaults['text'] = '{{ user.username }}';
+
+ return $defaults;
+ }
+
+ /**
+ * Search all users for the picker
+ *
+ * @return \Kirby\Cms\Users|null
+ */
+ public function items()
+ {
+ $model = $this->options['model'];
+
+ // find the right default query
+ if (empty($this->options['query']) === false) {
+ $query = $this->options['query'];
+ } elseif (is_a($model, 'Kirby\Cms\User') === true) {
+ $query = 'user.siblings';
+ } else {
+ $query = 'kirby.users';
+ }
+
+ // fetch all users for the picker
+ $users = $model->query($query);
+
+ // catch invalid data
+ if (is_a($users, 'Kirby\Cms\Users') === false) {
+ throw new InvalidArgumentException('Your query must return a set of users');
+ }
+
+ // search
+ $users = $this->search($users);
+
+ // sort
+ $users = $users->sortBy('username', 'asc');
+
+ // paginate
+ return $this->paginate($users);
+ }
+}
diff --git a/src/Data/Data.php b/src/Data/Data.php
index eadc9fb5f6..a53a085711 100644
--- a/src/Data/Data.php
+++ b/src/Data/Data.php
@@ -50,7 +50,7 @@ class Data
/**
* Handler getter
*
- * @param string $type
+ * @param string $type
* @return \Kirby\Data\Handler
*/
public static function handler(string $type)
@@ -73,8 +73,8 @@ public static function handler(string $type)
/**
* Decodes data with the specified handler
*
- * @param string $data
- * @param string $type
+ * @param string $data
+ * @param string $type
* @return array
*/
public static function decode(string $data = null, string $type): array
@@ -85,8 +85,8 @@ public static function decode(string $data = null, string $type): array
/**
* Encodes data with the specified handler
*
- * @param array $data
- * @param string $type
+ * @param array $data
+ * @param string $type
* @return string
*/
public static function encode(array $data = null, string $type): string
@@ -99,8 +99,8 @@ public static function encode(array $data = null, string $type): string
* the data handler is automatically chosen by
* the extension if not specified
*
- * @param string $file
- * @param string $type
+ * @param string $file
+ * @param string $type
* @return array
*/
public static function read(string $file, string $type = null): array
@@ -113,10 +113,10 @@ public static function read(string $file, string $type = null): array
* the data handler is automatically chosen by
* the extension if not specified
*
- * @param string $file
- * @param array $data
- * @param string $type
- * @return boolean
+ * @param string $file
+ * @param array $data
+ * @param string $type
+ * @return bool
*/
public static function write(string $file = null, array $data = [], string $type = null): bool
{
diff --git a/src/Data/Handler.php b/src/Data/Handler.php
index d47bf57901..6cf6a351d4 100644
--- a/src/Data/Handler.php
+++ b/src/Data/Handler.php
@@ -23,7 +23,7 @@ abstract class Handler
*
* Needs to throw an Exception if the file can't be parsed.
*
- * @param string $string
+ * @param string $string
* @return array
*/
abstract public static function decode($string): array;
@@ -31,7 +31,7 @@ abstract public static function decode($string): array;
/**
* Converts an array to an encoded string
*
- * @param mixed $data
+ * @param mixed $data
* @return string
*/
abstract public static function encode($data): string;
@@ -39,7 +39,7 @@ abstract public static function encode($data): string;
/**
* Reads data from a file
*
- * @param string $file
+ * @param string $file
* @return array
*/
public static function read(string $file): array
@@ -54,9 +54,9 @@ public static function read(string $file): array
/**
* Writes data to a file
*
- * @param string $file
- * @param array $data
- * @return boolean
+ * @param string $file
+ * @param array $data
+ * @return bool
*/
public static function write(string $file = null, array $data = []): bool
{
diff --git a/src/Data/Json.php b/src/Data/Json.php
index 8eb553ea96..88d741fe46 100644
--- a/src/Data/Json.php
+++ b/src/Data/Json.php
@@ -18,7 +18,7 @@ class Json extends Handler
/**
* Converts an array to an encoded JSON string
*
- * @param mixed $data
+ * @param mixed $data
* @return string
*/
public static function encode($data): string
diff --git a/src/Data/PHP.php b/src/Data/PHP.php
index 7251e3b546..93f8871582 100644
--- a/src/Data/PHP.php
+++ b/src/Data/PHP.php
@@ -19,8 +19,8 @@ class PHP extends Handler
/**
* Converts an array to PHP file content
*
- * @param mixed $data
- * @param string $indent For internal use only
+ * @param mixed $data
+ * @param string $indent For internal use only
* @return string
*/
public static function encode($data, $indent = ''): string
@@ -48,7 +48,7 @@ public static function encode($data, $indent = ''): string
/**
* PHP arrays don't have to be decoded
*
- * @param array $array
+ * @param array $array
* @return array
*/
public static function decode($array): array
@@ -59,7 +59,7 @@ public static function decode($array): array
/**
* Reads data from a file
*
- * @param string $file
+ * @param string $file
* @return array
*/
public static function read(string $file): array
@@ -74,9 +74,9 @@ public static function read(string $file): array
/**
* Creates a PHP file with the given data
*
- * @param string $file
- * @param array $data
- * @return boolean
+ * @param string $file
+ * @param array $data
+ * @return bool
*/
public static function write(string $file = null, array $data = []): bool
{
diff --git a/src/Data/Txt.php b/src/Data/Txt.php
index 3d8e744c04..d76c1d2460 100644
--- a/src/Data/Txt.php
+++ b/src/Data/Txt.php
@@ -18,7 +18,7 @@ class Txt extends Handler
/**
* Converts an array to an encoded Kirby txt string
*
- * @param mixed $data
+ * @param mixed $data
* @return string
*/
public static function encode($data): string
@@ -41,7 +41,7 @@ public static function encode($data): string
/**
* Helper for converting the value
*
- * @param array|string $value
+ * @param array|string $value
* @return string
*/
protected static function encodeValue($value): string
@@ -63,8 +63,8 @@ protected static function encodeValue($value): string
/**
* Helper for converting the key and value to the result string
*
- * @param string $key
- * @param string $value
+ * @param string $key
+ * @param string $value
* @return string
*/
protected static function encodeResult(string $key, string $value): string
@@ -86,7 +86,7 @@ protected static function encodeResult(string $key, string $value): string
/**
* Parses a Kirby txt string and returns a multi-dimensional array
*
- * @param string $string
+ * @param string $string
* @return array
*/
public static function decode($string): array
diff --git a/src/Data/Yaml.php b/src/Data/Yaml.php
index 2e7cda27e8..0b5f321c0a 100644
--- a/src/Data/Yaml.php
+++ b/src/Data/Yaml.php
@@ -19,7 +19,7 @@ class Yaml extends Handler
/**
* Converts an array to an encoded YAML string
*
- * @param mixed $data
+ * @param mixed $data
* @return string
*/
public static function encode($data): string
@@ -42,7 +42,7 @@ public static function encode($data): string
/**
* Parses an encoded YAML string and returns a multi-dimensional array
*
- * @param string $yaml
+ * @param string $yaml
* @return array
*/
public static function decode($yaml): array
diff --git a/src/Database/Database.php b/src/Database/Database.php
index 30bd1f751d..1de9bd299f 100644
--- a/src/Database/Database.php
+++ b/src/Database/Database.php
@@ -64,7 +64,7 @@ class Database
/**
* Set to true to throw exceptions on failed queries
*
- * @var boolean
+ * @var bool
*/
protected $fail = false;
@@ -232,7 +232,7 @@ public function connection()
/**
* Sets the exception mode for the next query
*
- * @param boolean $fail
+ * @param bool $fail
* @return \Kirby\Database\Database
*/
public function fail(bool $fail = true)
@@ -358,7 +358,7 @@ public function name(): ?string
*
* @param string $query
* @param array $bindings
- * @return boolean
+ * @return bool
*/
protected function hit(string $query, array $bindings = []): bool
{
@@ -455,7 +455,7 @@ public function query(string $query, array $bindings = [], array $params = [])
*
* @param string $query
* @param array $bindings
- * @return boolean
+ * @return bool
*/
public function execute(string $query, array $bindings = []): bool
{
@@ -491,7 +491,7 @@ public function table(string $table)
* Checks if a table exists in the current database
*
* @param string $table
- * @return boolean
+ * @return bool
*/
public function validateTable(string $table): bool
{
@@ -515,7 +515,7 @@ public function validateTable(string $table): bool
*
* @param string $table
* @param string $column
- * @return boolean
+ * @return bool
*/
public function validateColumn(string $table, string $column): bool
{
@@ -544,7 +544,7 @@ public function validateColumn(string $table, string $column): bool
*
* @param string $table
* @param array $columns
- * @return boolean
+ * @return bool
*/
public function createTable($table, $columns = []): bool
{
@@ -566,7 +566,7 @@ public function createTable($table, $columns = []): bool
* Drops a table
*
* @param string $table
- * @return boolean
+ * @return bool
*/
public function dropTable($table): bool
{
diff --git a/src/Database/Query.php b/src/Database/Query.php
index 660044f26f..c1e66847d3 100644
--- a/src/Database/Query.php
+++ b/src/Database/Query.php
@@ -87,7 +87,7 @@ class Query
/**
* Boolean for if exceptions should be thrown on failing queries
*
- * @var boolean
+ * @var bool
*/
protected $fail = false;
@@ -129,21 +129,21 @@ class Query
/**
* The offset, which should be applied to the select query
*
- * @var integer
+ * @var int
*/
protected $offset = 0;
/**
* The limit, which should be applied to the select query
*
- * @var integer
+ * @var int
*/
protected $limit;
/**
* Boolean to enable query debugging
*
- * @var boolean
+ * @var bool
*/
protected $debug = false;
@@ -184,7 +184,7 @@ protected function reset()
* If enabled, the query will return an array with all important info about
* the query instead of actually executing the query and returning results
*
- * @param boolean $debug
+ * @param bool $debug
* @return \Kirby\Database\Query
*/
public function debug(bool $debug = true)
@@ -196,7 +196,7 @@ public function debug(bool $debug = true)
/**
* Enables distinct select clauses.
*
- * @param boolean $distinct
+ * @param bool $distinct
* @return \Kirby\Database\Query
*/
public function distinct(bool $distinct = true)
@@ -209,7 +209,7 @@ public function distinct(bool $distinct = true)
* Enables failing queries.
* If enabled queries will no longer fail silently but throw an exception
*
- * @param boolean $fail
+ * @param bool $fail
* @return \Kirby\Database\Query
*/
public function fail(bool $fail = true)
@@ -880,7 +880,7 @@ public function insert($values = null)
*
* @param array $values You can pass values here or set them with ->values() before
* @param mixed $where You can pass a where clause here or set it with ->where() before
- * @return boolean
+ * @return bool
*/
public function update($values = null, $where = null)
{
@@ -891,7 +891,7 @@ public function update($values = null, $where = null)
* Fires a delete query
*
* @param mixed $where You can pass a where clause here or set it with ->where() before
- * @return boolean
+ * @return bool
*/
public function delete($where = null)
{
diff --git a/src/Database/Sql.php b/src/Database/Sql.php
index 5bd0a3f0db..09e18fce7b 100644
--- a/src/Database/Sql.php
+++ b/src/Database/Sql.php
@@ -112,7 +112,7 @@ public function columnDefault(array $column): array
*
* @param string $table
* @param string $column
- * @param boolean $enforceQualified
+ * @param bool $enforceQualified
* @return string|null
*/
public function columnName(string $table, string $column, bool $enforceQualified = false): ?string
@@ -483,8 +483,8 @@ public function joins(array $joins = null): array
/**
* Creates a limit and offset query instruction
*
- * @param integer $offset
- * @param integer|null $limit
+ * @param int $offset
+ * @param int|null $limit
* @return array
*/
public function limit(int $offset = 0, int $limit = null): array
@@ -780,7 +780,7 @@ public function update(array $params = []): array
*
* @param string $table
* @param string $column
- * @return boolean
+ * @return bool
*/
public function validateColumn(string $table, string $column): bool
{
@@ -797,8 +797,8 @@ public function validateColumn(string $table, string $column): bool
* @param string $table Table name
* @param mixed $values A value string or array of values
* @param string $separator A separator which should be used to join values
- * @param boolean $set If true builds a set list of values for update clauses
- * @param boolean $enforceQualified Always use fully qualified column names
+ * @param bool $set If true builds a set list of values for update clauses
+ * @param bool $enforceQualified Always use fully qualified column names
*/
public function values(string $table, $values, string $separator = ', ', bool $set = true, bool $enforceQualified = false): array
{
diff --git a/src/Exception/ErrorPageException.php b/src/Exception/ErrorPageException.php
new file mode 100644
index 0000000000..43bfd33993
--- /dev/null
+++ b/src/Exception/ErrorPageException.php
@@ -0,0 +1,20 @@
+
+ * @link https://getkirby.com
+ * @copyright Bastian Allgeier GmbH
+ * @license https://opensource.org/licenses/MIT
+ */
+class ErrorPageException extends Exception
+{
+ protected static $defaultKey = 'errorPage';
+ protected static $defaultFallback = 'Triggered error page';
+ protected static $defaultHttpCode = 404;
+}
diff --git a/src/Exception/Exception.php b/src/Exception/Exception.php
index 303a7665b1..f6bc58834f 100644
--- a/src/Exception/Exception.php
+++ b/src/Exception/Exception.php
@@ -42,7 +42,7 @@ class Exception extends \Exception
/**
* Whether the exception message could be translated into the user's language
*
- * @var boolean
+ * @var bool
*/
protected $isTranslated = true;
@@ -194,7 +194,7 @@ final public function getHttpCode(): int
* Returns whether the exception message could
* be translated into the user's language
*
- * @return boolean
+ * @return bool
*/
final public function isTranslated(): bool
{
diff --git a/src/Form/Field.php b/src/Form/Field.php
index 2d5f728f9c..fddf0e487f 100644
--- a/src/Form/Field.php
+++ b/src/Form/Field.php
@@ -203,6 +203,13 @@ public static function defaults(): array
return $this->model()->toString($this->default);
},
+ 'help' => function () {
+ if ($this->help) {
+ $help = $this->model()->toString($this->help);
+ $help = $this->kirby()->kirbytext($help);
+ return $help;
+ }
+ },
'label' => function () {
if ($this->label !== null) {
return $this->model()->toString($this->label);
diff --git a/src/Form/Form.php b/src/Form/Form.php
index f3847e3ea9..3dd04102a3 100644
--- a/src/Form/Form.php
+++ b/src/Form/Form.php
@@ -61,14 +61,7 @@ public function __construct(array $props)
try {
$field = new Field($props['type'], $props);
} catch (Throwable $e) {
- $props = array_merge($props, [
- 'name' => $props['name'],
- 'label' => 'Error in "' . $props['name'] . '" field',
- 'theme' => 'negative',
- 'text' => $e->getMessage(),
- ]);
-
- $field = new Field('info', $props);
+ $field = static::exceptionField($e, $props);
}
if ($field->save() !== false) {
@@ -127,6 +120,17 @@ public function errors(): array
return $this->errors;
}
+ public static function exceptionField(Throwable $exception, array $props = [])
+ {
+ $props = array_merge($props, [
+ 'label' => 'Error in "' . $props['name'] . '" field',
+ 'theme' => 'negative',
+ 'text' => strip_tags($exception->getMessage()),
+ ]);
+
+ return new Field('info', $props);
+ }
+
public function fields()
{
return $this->fields;
diff --git a/src/Http/Cookie.php b/src/Http/Cookie.php
index 8e2f03c6e7..41285e5fc2 100644
--- a/src/Http/Cookie.php
+++ b/src/Http/Cookie.php
@@ -32,12 +32,12 @@ class Cookie
*
*
*
- * @param string $key The name of the cookie
- * @param string $value The cookie content
- * @param array $options Array of options:
- * lifetime, path, domain, secure, httpOnly
- * @return boolean true: cookie was created,
- * false: cookie creation failed
+ * @param string $key The name of the cookie
+ * @param string $value The cookie content
+ * @param array $options Array of options:
+ * lifetime, path, domain, secure, httpOnly
+ * @return bool true: cookie was created,
+ * false: cookie creation failed
*/
public static function set(string $key, string $value, array $options = []): bool
{
@@ -61,7 +61,7 @@ public static function set(string $key, string $value, array $options = []): boo
/**
* Calculates the lifetime for a cookie
*
- * @param int $minutes Number of minutes or timestamp
+ * @param int $minutes Number of minutes or timestamp
* @return int
*/
public static function lifetime(int $minutes): int
@@ -87,12 +87,12 @@ public static function lifetime(int $minutes): int
*
*
*
- * @param string $key The name of the cookie
- * @param string $value The cookie content
- * @param array $options Array of options:
- * path, domain, secure, httpOnly
- * @return boolean true: cookie was created,
- * false: cookie creation failed
+ * @param string $key The name of the cookie
+ * @param string $value The cookie content
+ * @param array $options Array of options:
+ * path, domain, secure, httpOnly
+ * @return bool true: cookie was created,
+ * false: cookie creation failed
*/
public static function forever(string $key, string $value, array $options = []): bool
{
@@ -110,10 +110,10 @@ public static function forever(string $key, string $value, array $options = []):
*
*
*
- * @param string|null $key The name of the cookie
- * @param string|null $default The default value, which should be returned
- * if the cookie has not been found
- * @return mixed The found value
+ * @param string|null $key The name of the cookie
+ * @param string|null $default The default value, which should be returned
+ * if the cookie has not been found
+ * @return mixed The found value
*/
public static function get(string $key = null, string $default = null)
{
@@ -127,8 +127,8 @@ public static function get(string $key = null, string $default = null)
/**
* Checks if a cookie exists
*
- * @param string $key
- * @return boolean
+ * @param string $key
+ * @return bool
*/
public static function exists(string $key): bool
{
@@ -139,7 +139,7 @@ public static function exists(string $key): bool
* Creates a HMAC for the cookie value
* Used as a cookie signature to prevent easy tampering with cookie data
*
- * @param string $value
+ * @param string $value
* @return string
*/
protected static function hmac(string $value): string
@@ -151,7 +151,7 @@ protected static function hmac(string $value): string
* Parses the hashed value from a cookie
* and tries to extract the value
*
- * @param string $string
+ * @param string $string
* @return mixed
*/
protected static function parse(string $string)
@@ -190,9 +190,9 @@ protected static function parse(string $string)
*
*
*
- * @param string $key The name of the cookie
- * @return boolean true: the cookie has been removed,
- * false: the cookie could not be removed
+ * @param string $key The name of the cookie
+ * @return bool true: the cookie has been removed,
+ * false: the cookie could not be removed
*/
public static function remove(string $key): bool
{
diff --git a/src/Http/Header.php b/src/Http/Header.php
index f0d7327bf3..46f91382ec 100644
--- a/src/Http/Header.php
+++ b/src/Http/Header.php
@@ -58,7 +58,7 @@ class Header
*
* @param string $mime
* @param string $charset
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function contentType(string $mime, string $charset = 'UTF-8', bool $send = true)
@@ -108,7 +108,7 @@ public static function create($key, string $value = null): string
*
* @param string $mime
* @param string $charset
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function type(string $mime, string $charset = 'UTF-8', bool $send = true)
@@ -124,7 +124,7 @@ public static function type(string $mime, string $charset = 'UTF-8', bool $send
* as 3 digits followed by a space and a message, e.g. '999 Custom Status'.
*
* @param int|string $code The HTTP status code
- * @param boolean $send If set to false the header will be returned instead
+ * @param bool $send If set to false the header will be returned instead
* @return string|void
*/
public static function status($code = null, bool $send = true)
@@ -154,7 +154,7 @@ public static function status($code = null, bool $send = true)
/**
* Sends a 200 header
*
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function success(bool $send = true)
@@ -165,7 +165,7 @@ public static function success(bool $send = true)
/**
* Sends a 201 header
*
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function created(bool $send = true)
@@ -176,7 +176,7 @@ public static function created(bool $send = true)
/**
* Sends a 202 header
*
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function accepted(bool $send = true)
@@ -187,7 +187,7 @@ public static function accepted(bool $send = true)
/**
* Sends a 400 header
*
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function error(bool $send = true)
@@ -198,7 +198,7 @@ public static function error(bool $send = true)
/**
* Sends a 403 header
*
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function forbidden(bool $send = true)
@@ -209,7 +209,7 @@ public static function forbidden(bool $send = true)
/**
* Sends a 404 header
*
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function notfound(bool $send = true)
@@ -220,7 +220,7 @@ public static function notfound(bool $send = true)
/**
* Sends a 404 header
*
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function missing(bool $send = true)
@@ -231,7 +231,7 @@ public static function missing(bool $send = true)
/**
* Sends a 410 header
*
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function gone(bool $send = true)
@@ -242,7 +242,7 @@ public static function gone(bool $send = true)
/**
* Sends a 500 header
*
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function panic(bool $send = true)
@@ -253,7 +253,7 @@ public static function panic(bool $send = true)
/**
* Sends a 503 header
*
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function unavailable(bool $send = true)
@@ -266,7 +266,7 @@ public static function unavailable(bool $send = true)
*
* @param string $url
* @param int $code
- * @param boolean $send
+ * @param bool $send
* @return string|void
*/
public static function redirect(string $url, int $code = 302, bool $send = true)
diff --git a/src/Http/Params.php b/src/Http/Params.php
index 71d7bb36c9..5d0fa44c8a 100644
--- a/src/Http/Params.php
+++ b/src/Http/Params.php
@@ -116,8 +116,8 @@ public static function separator(): string
* Converts the params object to a params string
* which can then be used in the URL builder again
*
- * @param boolean $leadingSlash
- * @param boolean $trailingSlash
+ * @param bool $leadingSlash
+ * @param bool $trailingSlash
* @return string|null
*/
public function toString($leadingSlash = false, $trailingSlash = false): string
diff --git a/src/Http/Remote.php b/src/Http/Remote.php
index 686b5780e4..b5dbce7d87 100644
--- a/src/Http/Remote.php
+++ b/src/Http/Remote.php
@@ -113,7 +113,7 @@ public static function __callStatic(string $method, array $arguments = [])
/**
* Returns the http status code
*
- * @return integer|null
+ * @return int|null
*/
public function code(): ?int
{
diff --git a/src/Http/Request.php b/src/Http/Request.php
index 7b77e8e32b..c83645a71d 100644
--- a/src/Http/Request.php
+++ b/src/Http/Request.php
@@ -142,16 +142,6 @@ public function __debugInfo(): array
];
}
- /**
- * Detects ajax requests
- * @deprecated 3.1.0 No longer reliable, especially with the fetch api.
- * @return boolean
- */
- public function ajax(): bool
- {
- return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
- }
-
/**
* Returns the Auth object if authentication is set
*
@@ -191,7 +181,7 @@ public function body()
/**
* Checks if the request has been made from the command line
*
- * @return boolean
+ * @return bool
*/
public function cli(): bool
{
@@ -232,7 +222,7 @@ public function domain(): string
* Fetches a single file array
* from the Files object by key
*
- * @param string $key
+ * @param string $key
* @return array|null
*/
public function file(string $key)
@@ -316,8 +306,8 @@ public function headers(): array
* Checks if the given method name
* matches the name of the request method.
*
- * @param string $method
- * @return boolean
+ * @param string $method
+ * @return bool
*/
public function is(string $method): bool
{
@@ -363,7 +353,7 @@ public function query()
/**
* Checks for a valid SSL connection
*
- * @return boolean
+ * @return bool
*/
public function ssl(): bool
{
diff --git a/src/Http/Request/Data.php b/src/Http/Request/Data.php
index aaf6558ac6..0a6bc7f82d 100644
--- a/src/Http/Request/Data.php
+++ b/src/Http/Request/Data.php
@@ -44,8 +44,8 @@ abstract public function data(): array;
* of the data array by key or multiple values by
* passing an array of keys.
*
- * @param string|array $key
- * @param mixed|null $default
+ * @param string|array $key
+ * @param mixed|null $default
* @return mixed
*/
public function get($key, $default = null)
diff --git a/src/Http/Response.php b/src/Http/Response.php
index 1c9d3097b5..ca7596a497 100644
--- a/src/Http/Response.php
+++ b/src/Http/Response.php
@@ -58,11 +58,11 @@ class Response
/**
* Creates a new response object
*
- * @param string $body
- * @param string $type
- * @param integer $code
- * @param array $headers
- * @param string $charset
+ * @param string $body
+ * @param string $type
+ * @param int $code
+ * @param array $headers
+ * @param string $charset
*/
public function __construct($body = '', ?string $type = null, ?int $code = null, ?array $headers = null, ?string $charset = null)
{
@@ -194,7 +194,7 @@ public static function file(string $file)
/**
* Getter for single headers
*
- * @param string $key Name of the header
+ * @param string $key Name of the header
* @return string|null
*/
public function header(string $key): ?string
@@ -217,8 +217,8 @@ public function headers(): array
* header and automatic conversion of arrays.
*
* @param string|array $body
- * @param integer $code
- * @param boolean $pretty
+ * @param int $code
+ * @param bool $pretty
* @param array $headers
* @return self
*/
@@ -242,7 +242,7 @@ public static function json($body = '', ?int $code = null, ?bool $pretty = null,
* given location.
*
* @param string $location
- * @param integer $code
+ * @param int $code
* @return self
*/
public static function redirect(?string $location = null, ?int $code = null)
diff --git a/src/Http/Route.php b/src/Http/Route.php
index 7f5c33edb6..eff1891758 100644
--- a/src/Http/Route.php
+++ b/src/Http/Route.php
@@ -90,7 +90,7 @@ public function __call(string $key, array $arguments = null)
*
* @param string|array $pattern
* @param string|array $method
- * @param Closure $action
+ * @param Closure $action
* @param array $attributes
*/
public function __construct($pattern, $method = 'GET', Closure $action, array $attributes = [])
@@ -177,7 +177,7 @@ public function pattern(): string
* Converts the pattern into a full regular
* expression by replacing all the wildcards
*
- * @param string $pattern
+ * @param string $pattern
* @return string
*/
public function regex(string $pattern): string
@@ -201,8 +201,8 @@ public function regex(string $pattern): string
* Tries to match the path with the regular expression and
* extracts all arguments for the Route action
*
- * @param string $pattern
- * @param string $path
+ * @param string $pattern
+ * @param string $path
* @return array|false
*/
public function parse(string $pattern, string $path)
diff --git a/src/Http/Router.php b/src/Http/Router.php
index 7a71fb1d06..90903f4251 100644
--- a/src/Http/Router.php
+++ b/src/Http/Router.php
@@ -81,9 +81,9 @@ public function __construct(array $routes = [])
* the appropriate arguments and a Result
* object.
*
- * @param string $path
- * @param string $method
- * @param Closure|null $callback
+ * @param string $path
+ * @param string $method
+ * @param Closure|null $callback
* @return mixed
*/
public function call(string $path = null, string $method = 'GET', Closure $callback = null)
@@ -126,9 +126,9 @@ public function call(string $path = null, string $method = 'GET', Closure $callb
* find matches and return all the found
* arguments in the path.
*
- * @param string $path
- * @param string $method
- * @param array $ignore
+ * @param string $path
+ * @param string $method
+ * @param array $ignore
* @return \Kirby\Http\Route|null
*/
public function find(string $path, string $method, array $ignore = null)
diff --git a/src/Http/Server.php b/src/Http/Server.php
index 132f4740aa..1ccf919eeb 100644
--- a/src/Http/Server.php
+++ b/src/Http/Server.php
@@ -34,7 +34,7 @@ public static function address(): string
/**
* Checks if the request is being served by the CLI
*
- * @return boolean
+ * @return bool
*/
public static function cli(): bool
{
@@ -66,10 +66,10 @@ public static function cli(): bool
* // returns the whole server array
*
*
- * @param mixed $key The key to look for. Pass false or null to
- * return the entire server array.
- * @param mixed $default Optional default value, which should be
- * returned if no element has been found
+ * @param mixed $key The key to look for. Pass false or null to
+ * return the entire server array.
+ * @param mixed $default Optional default value, which should be
+ * returned if no element has been found
* @return mixed
*/
public static function get($key = null, $default = null)
@@ -86,8 +86,8 @@ public static function get($key = null, $default = null)
/**
* Help to sanitize some _SERVER keys
*
- * @param string $key
- * @param mixed $value
+ * @param string $key
+ * @param mixed $value
* @return mixed
*/
public static function sanitize(string $key, $value)
@@ -131,7 +131,7 @@ public static function port(bool $forwarded = false): int
/**
* Checks for a https request
*
- * @return boolean
+ * @return bool
*/
public static function https(): bool
{
diff --git a/src/Http/Uri.php b/src/Http/Uri.php
index ab46bea639..190ae89813 100644
--- a/src/Http/Uri.php
+++ b/src/Http/Uri.php
@@ -90,7 +90,7 @@ class Uri
protected $scheme = 'http';
/**
- * @var boolean
+ * @var bool
*/
protected $slash = false;
@@ -237,7 +237,7 @@ public function clone(array $props = [])
/**
* @param array $props
- * @param boolean $forwarded
+ * @param bool $forwarded
* @return self
*/
public static function current(array $props = [], bool $forwarded = false)
@@ -289,7 +289,7 @@ public function domain(): ?string
}
/**
- * @return boolean
+ * @return bool
*/
public function hasFragment(): bool
{
@@ -297,7 +297,7 @@ public function hasFragment(): bool
}
/**
- * @return boolean
+ * @return bool
*/
public function hasPath(): bool
{
@@ -305,7 +305,7 @@ public function hasPath(): bool
}
/**
- * @return boolean
+ * @return bool
*/
public function hasQuery(): bool
{
@@ -373,7 +373,7 @@ public function isAbsolute(): bool
}
/**
- * @param string|null $fragment
+ * @param string|null $fragment
* @return self
*/
public function setFragment(string $fragment = null)
@@ -383,7 +383,7 @@ public function setFragment(string $fragment = null)
}
/**
- * @param string $host
+ * @param string $host
* @return self
*/
public function setHost(string $host = null)
@@ -393,7 +393,7 @@ public function setHost(string $host = null)
}
/**
- * @param Kirby\Http\Params|string|array|null $params
+ * @param \Kirby\Http\Params|string|array|null $params
* @return self
*/
public function setParams($params = null)
@@ -403,7 +403,7 @@ public function setParams($params = null)
}
/**
- * @param string|null $password
+ * @param string|null $password
* @return self
*/
public function setPassword(string $password = null)
@@ -453,7 +453,7 @@ public function setQuery($query = null)
}
/**
- * @param string $scheme
+ * @param string $scheme
* @return self
*/
public function setScheme(string $scheme = null)
@@ -480,7 +480,7 @@ public function setSlash(bool $slash = false)
}
/**
- * @param string|null $username
+ * @param string|null $username
* @return self
*/
public function setUsername(string $username = null)
diff --git a/src/Http/Url.php b/src/Http/Url.php
index fd3396ebf9..da21800419 100644
--- a/src/Http/Url.php
+++ b/src/Http/Url.php
@@ -112,7 +112,7 @@ public static function index(array $props = [], bool $forwarded = false): string
* Checks if an URL is absolute
*
* @param string $url
- * @return boolean
+ * @return bool
*/
public static function isAbsolute(string $url = null): bool
{
@@ -194,7 +194,7 @@ public static function last(): string
*
* @param string $url
* @param int $length
- * @param boolean $base
+ * @param bool $base
* @param string $rep
* @return string
*/
diff --git a/src/Http/Visitor.php b/src/Http/Visitor.php
index a9204eed75..4d4b9586b4 100644
--- a/src/Http/Visitor.php
+++ b/src/Http/Visitor.php
@@ -66,7 +66,7 @@ public function __construct(array $arguments = [])
* provided or returns the user's
* accepted language otherwise
*
- * @param string|null $acceptedLanguage
+ * @param string|null $acceptedLanguage
* @return \Kirby\Toolkit\Obj|\Kirby\Http\Visitor|null
*/
public function acceptedLanguage(string $acceptedLanguage = null)
@@ -133,7 +133,7 @@ public function acceptsLanguage(string $code): bool
* provided or returns the user's
* accepted mime type otherwise
*
- * @param string|null $acceptedMimeType
+ * @param string|null $acceptedMimeType
* @return \Kirby\Toolkit\Obj|\Kirby\Http\Visitor
*/
public function acceptedMimeType(string $acceptedMimeType = null)
@@ -169,20 +169,57 @@ public function acceptedMimeTypes()
/**
* Checks if the user accepts the given mime type
*
- * @param string $mimeType
- * @return boolean
+ * @param string $mimeType
+ * @return bool
*/
public function acceptsMimeType(string $mimeType): bool
{
return Mime::isAccepted($mimeType, $this->acceptedMimeType);
}
+ /**
+ * Returns the MIME type from the provided list that
+ * is most accepted (= preferred) by the visitor
+ *
+ * @param string ...$mimeTypes MIME types to query for
+ * @return string|null Preferred MIME type
+ */
+ public function preferredMimeType(string ...$mimeTypes): ?string
+ {
+ foreach ($this->acceptedMimeTypes() as $acceptedMime) {
+ // look for direct matches
+ if (in_array($acceptedMime->type(), $mimeTypes)) {
+ return $acceptedMime->type();
+ }
+
+ // test each option against wildcard `Accept` values
+ foreach ($mimeTypes as $expectedMime) {
+ if (Mime::matches($expectedMime, $acceptedMime->type()) === true) {
+ return $expectedMime;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns true if the visitor prefers a JSON response over
+ * an HTML response based on the `Accept` request header
+ *
+ * @return bool
+ */
+ public function prefersJson(): bool
+ {
+ return $this->preferredMimeType('application/json', 'text/html') === 'application/json';
+ }
+
/**
* Sets the ip address if provided
* or returns the ip of the current
* visitor otherwise
*
- * @param string|null $ip
+ * @param string|null $ip
* @return string|Visitor|null
*/
public function ip(string $ip = null)
@@ -199,7 +236,7 @@ public function ip(string $ip = null)
* or returns the user agent string of
* the current visitor otherwise
*
- * @param string|null $userAgent
+ * @param string|null $userAgent
* @return string|Visitor|null
*/
public function userAgent(string $userAgent = null)
diff --git a/src/Image/Dimensions.php b/src/Image/Dimensions.php
index cd820145f0..ed20b885f2 100644
--- a/src/Image/Dimensions.php
+++ b/src/Image/Dimensions.php
@@ -65,9 +65,9 @@ public function __toString(): string
/**
* Crops the dimensions by width and height
*
- * @param int $width
- * @param int $height
- * @return self
+ * @param int $width
+ * @param int $height
+ * @return self
*/
public function crop(int $width, int $height = null)
{
@@ -107,9 +107,9 @@ public function height()
*
*
*
- * @param int $box the max width and/or height
- * @param bool $force If true, the dimensions will be
- * upscaled to fit the box if smaller
+ * @param int $box the max width and/or height
+ * @param bool $force If true, the dimensions will be
+ * upscaled to fit the box if smaller
* @return self object with recalculated dimensions
*/
public function fit(int $box, bool $force = false)
@@ -159,10 +159,10 @@ public function fit(int $box, bool $force = false)
*
*
*
- * @param int $fit the max height
- * @param bool $force If true, the dimensions will be
- * upscaled to fit the box if smaller
- * @return self object with recalculated dimensions
+ * @param int $fit the max height
+ * @param bool $force If true, the dimensions will be
+ * upscaled to fit the box if smaller
+ * @return self object with recalculated dimensions
*/
public function fitHeight(int $fit = null, bool $force = false)
{
@@ -172,11 +172,11 @@ public function fitHeight(int $fit = null, bool $force = false)
/**
* Helper for fitWidth and fitHeight methods
*
- * @param string $ref reference (width or height)
- * @param int $fit the max width
- * @param bool $force If true, the dimensions will be
- * upscaled to fit the box if smaller
- * @return self object with recalculated dimensions
+ * @param string $ref reference (width or height)
+ * @param int $fit the max width
+ * @param bool $force If true, the dimensions will be
+ * upscaled to fit the box if smaller
+ * @return self object with recalculated dimensions
*/
protected function fitSize(string $ref, int $fit = null, bool $force = false)
{
@@ -212,10 +212,10 @@ protected function fitSize(string $ref, int $fit = null, bool $force = false)
*
*
*
- * @param int $fit the max width
- * @param bool $force If true, the dimensions will be
- * upscaled to fit the box if smaller
- * @return self object with recalculated dimensions
+ * @param int $fit the max width
+ * @param bool $force If true, the dimensions will be
+ * upscaled to fit the box if smaller
+ * @return self object with recalculated dimensions
*/
public function fitWidth(int $fit = null, bool $force = false)
{
@@ -225,10 +225,10 @@ public function fitWidth(int $fit = null, bool $force = false)
/**
* Recalculates the dimensions by the width and height
*
- * @param int $width the max height
- * @param int $height the max width
- * @param bool $force
- * @return self
+ * @param int $width the max height
+ * @param int $height the max width
+ * @param bool $force
+ * @return self
*/
public function fitWidthAndHeight(int $width = null, int $height = null, bool $force = false)
{
@@ -362,10 +362,10 @@ public function ratio(): float
}
/**
- * @param int $width
- * @param int $height
- * @param bool $force
- * @return self
+ * @param int $width
+ * @param int $height
+ * @param bool $force
+ * @return self
*/
public function resize(int $width = null, int $height = null, bool $force = false)
{
@@ -385,7 +385,7 @@ public function square(): bool
/**
* Resize and crop
*
- * @param array $options
+ * @param array $options
* @return self
*/
public function thumb(array $options = [])
diff --git a/src/Image/Exif.php b/src/Image/Exif.php
index ef8393a74c..08aeef8cb7 100644
--- a/src/Image/Exif.php
+++ b/src/Image/Exif.php
@@ -173,7 +173,7 @@ public function iso()
/**
* Checks if this is a color picture
*
- * @return boolean|null
+ * @return bool|null
*/
public function isColor()
{
@@ -183,7 +183,7 @@ public function isColor()
/**
* Checks if this is a bw picture
*
- * @return boolean|null
+ * @return bool|null
*/
public function isBW(): bool
{
diff --git a/src/Image/Image.php b/src/Image/Image.php
index 2c30272604..a3be19ea01 100644
--- a/src/Image/Image.php
+++ b/src/Image/Image.php
@@ -42,8 +42,8 @@ class Image extends File
/**
* Constructor
*
- * @param string $root
- * @param string|null $url
+ * @param string $root
+ * @param string|null $url
*/
public function __construct(string $root = null, string $url = null)
{
@@ -126,7 +126,7 @@ public function exif()
/**
* Sends an appropriate header for the asset
*
- * @param boolean $send
+ * @param bool $send
* @return \Kirby\Http\Response|string
*/
public function header(bool $send = true)
@@ -147,7 +147,7 @@ public function height(): int
}
/**
- * @param array $attr
+ * @param array $attr
* @return string
*/
public function html(array $attr = []): string
@@ -168,7 +168,7 @@ public function imagesize(): array
/**
* Checks if the dimensions of the asset are portrait
*
- * @return boolean
+ * @return bool
*/
public function isPortrait(): bool
{
@@ -178,7 +178,7 @@ public function isPortrait(): bool
/**
* Checks if the dimensions of the asset are landscape
*
- * @return boolean
+ * @return bool
*/
public function isLandscape(): bool
{
@@ -188,7 +188,7 @@ public function isLandscape(): bool
/**
* Checks if the dimensions of the asset are square
*
- * @return boolean
+ * @return bool
*/
public function isSquare(): bool
{
diff --git a/src/Image/Location.php b/src/Image/Location.php
index 3b02735d07..2c4e386312 100644
--- a/src/Image/Location.php
+++ b/src/Image/Location.php
@@ -68,8 +68,8 @@ public function lng()
/**
* Converts the gps coordinates
*
- * @param string|array $coord
- * @param string $hemi
+ * @param string|array $coord
+ * @param string $hemi
* @return float
*/
protected function gps($coord, string $hemi): float
@@ -87,7 +87,7 @@ protected function gps($coord, string $hemi): float
/**
* Converts coordinates to floats
*
- * @param string $part
+ * @param string $part
* @return float
*/
protected function num(string $part): float
diff --git a/src/Session/AutoSession.php b/src/Session/AutoSession.php
index 82c9c8ed10..f6a420c69a 100644
--- a/src/Session/AutoSession.php
+++ b/src/Session/AutoSession.php
@@ -21,19 +21,13 @@ class AutoSession
/**
* Creates a new AutoSession instance
*
- * @param \Kirby\Session\SessionStore|string $store SessionStore object or a path to the storage directory (uses the FileSessionStore)
- * @param array $options Optional additional options:
- * - `durationNormal`: Duration of normal sessions in seconds
- * Defaults to 2 hours
- * - `durationLong`: Duration of "remember me" sessions in seconds
- * Defaults to 2 weeks
- * - `timeout`: Activity timeout in seconds (integer or false for none)
- * *Only* used for normal sessions
- * Defaults to `1800` (half an hour)
- * - `cookieName`: Name to use for the session cookie
- * Defaults to `kirby_session`
- * - `gcInterval`: How often should the garbage collector be run?
- * Integer or `false` for never; defaults to `100`
+ * @param \Kirby\Session\SessionStore|string $store SessionStore object or a path to the storage directory (uses the FileSessionStore)
+ * @param array $options Optional additional options:
+ * - `durationNormal`: Duration of normal sessions in seconds; defaults to 2 hours
+ * - `durationLong`: Duration of "remember me" sessions in seconds; defaults to 2 weeks
+ * - `timeout`: Activity timeout in seconds (integer or false for none); *only* used for normal sessions; defaults to `1800` (half an hour)
+ * - `cookieName`: Name to use for the session cookie; defaults to `kirby_session`
+ * - `gcInterval`: How often should the garbage collector be run?; integer or `false` for never; defaults to `100`
*/
public function __construct($store, array $options = [])
{
@@ -56,15 +50,10 @@ public function __construct($store, array $options = [])
/**
* Returns the automatic session
*
- * @param array $options Optional additional options:
- * - `detect`: Whether to allow sessions in the `Authorization` HTTP header (`true`)
- * or only in the session cookie (`false`)
- * Defaults to `false`
- * - `createMode`: When creating a new session, should it be set as a cookie or is it going
- * to be transmitted manually to be used in a header?
- * Defaults to `cookie`
- * - `long`: Whether the session is a long "remember me" session or a normal session
- * Defaults to `false`
+ * @param array $options Optional additional options:
+ * - `detect`: Whether to allow sessions in the `Authorization` HTTP header (`true`) or only in the session cookie (`false`); defaults to `false`
+ * - `createMode`: When creating a new session, should it be set as a cookie or is it going to be transmitted manually to be used in a header?; defaults to `cookie`
+ * - `long`: Whether the session is a long "remember me" session or a normal session; defaults to `false`
* @return \Kirby\Session\Session
*/
public function get(array $options = [])
@@ -139,15 +128,11 @@ public function get(array $options = [])
* Useful for custom applications like a password reset link
* Does *not* affect the automatic session
*
- * @param array $options Optional additional options:
- * - `startTime`: Time the session starts being valid (date string or timestamp)
- * Defaults to `now`
- * - `expiryTime`: Time the session expires (date string or timestamp)
- * Defaults to `+ 2 hours`
- * - `timeout`: Activity timeout in seconds (integer or false for none)
- * Defaults to `1800` (half an hour)
- * - `renewable`: Should it be possible to extend the expiry date?
- * Defaults to `true`
+ * @param array $options Optional additional options:
+ * - `startTime`: Time the session starts being valid (date string or timestamp); defaults to `now`
+ * - `expiryTime`: Time the session expires (date string or timestamp); defaults to `+ 2 hours`
+ * - `timeout`: Activity timeout in seconds (integer or false for none); defaults to `1800` (half an hour)
+ * - `renewable`: Should it be possible to extend the expiry date?; defaults to `true`
* @return \Kirby\Session\Session
*/
public function createManually(array $options = [])
diff --git a/src/Session/FileSessionStore.php b/src/Session/FileSessionStore.php
index 6a03bf2d66..aeaee141ea 100644
--- a/src/Session/FileSessionStore.php
+++ b/src/Session/FileSessionStore.php
@@ -55,8 +55,8 @@ public function __construct(string $path)
* Needs to make sure that the session does not already exist
* and needs to reserve it by locking it exclusively.
*
- * @param int $expiryTime Timestamp
- * @return string Randomly generated session ID (without timestamp)
+ * @param int $expiryTime Timestamp
+ * @return string Randomly generated session ID (without timestamp)
*/
public function createId(int $expiryTime): string
{
@@ -89,10 +89,10 @@ public function createId(int $expiryTime): string
/**
* Checks if the given session exists
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
- * @return boolean true: session exists,
- * false: session doesn't exist
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
+ * @return bool true: session exists,
+ * false: session doesn't exist
*/
public function exists(int $expiryTime, string $id): bool
{
@@ -108,8 +108,8 @@ public function exists(int $expiryTime, string $id): bool
*
* Needs to throw an Exception on error.
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
* @return void
*/
public function lock(int $expiryTime, string $id)
@@ -146,8 +146,8 @@ public function lock(int $expiryTime, string $id)
*
* Needs to throw an Exception on error.
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
* @return void
*/
public function unlock(int $expiryTime, string $id)
@@ -187,8 +187,8 @@ public function unlock(int $expiryTime, string $id)
*
* Needs to throw an Exception on error.
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
* @return string
*/
public function get(int $expiryTime, string $id): string
@@ -250,9 +250,9 @@ public function get(int $expiryTime, string $id): string
* Needs to make sure that the session exists.
* Needs to throw an Exception on error.
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
- * @param string $data Session data to write
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
+ * @param string $data Session data to write
* @return void
*/
public function set(int $expiryTime, string $id, string $data)
@@ -303,8 +303,8 @@ public function set(int $expiryTime, string $id, string $data)
*
* Needs to throw an Exception on error.
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
* @return void
*/
public function destroy(int $expiryTime, string $id)
@@ -392,8 +392,8 @@ public function __destruct()
/**
* Returns the combined name based on expiry time and ID
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
* @return string
*/
protected function name(int $expiryTime, string $id): string
@@ -404,7 +404,7 @@ protected function name(int $expiryTime, string $id): string
/**
* Returns the full path to the session file
*
- * @param string $name Combined name
+ * @param string $name Combined name
* @return string
*/
protected function path(string $name): string
@@ -415,8 +415,8 @@ protected function path(string $name): string
/**
* Returns a PHP file handle for a session
*
- * @param string $name Combined name
- * @return resource File handle
+ * @param string $name Combined name
+ * @return resource File handle
*/
protected function handle(string $name)
{
@@ -457,7 +457,7 @@ protected function handle(string $name)
/**
* Closes an open file handle
*
- * @param string $name Combined name
+ * @param string $name Combined name
* @return void
*/
protected function closeHandle(string $name)
diff --git a/src/Session/Session.php b/src/Session/Session.php
index cfd99a521e..3bdb0e8818 100644
--- a/src/Session/Session.php
+++ b/src/Session/Session.php
@@ -49,19 +49,14 @@ class Session
/**
* Creates a new Session instance
*
- * @param \Kirby\Session\Sessions $sessions Parent sessions object
- * @param string|null $token Session token or null for a new session
- * @param array $options Optional additional options:
- * - `mode`: Token transmission mode (cookie or manual)
- * Defaults to `cookie`
- * - `startTime`: Time the session starts being valid (date string or timestamp)
- * Defaults to `now`
- * - `expiryTime`: Time the session expires (date string or timestamp)
- * Defaults to `+ 2 hours`
- * - `timeout`: Activity timeout in seconds (integer or false for none)
- * Defaults to `1800` (half an hour)
- * - `renewable`: Should it be possible to extend the expiry date?
- * Defaults to `true`
+ * @param \Kirby\Session\Sessions $sessions Parent sessions object
+ * @param string|null $token Session token or null for a new session
+ * @param array $options Optional additional options:
+ * - `mode`: Token transmission mode (cookie or manual); defaults to `cookie`
+ * - `startTime`: Time the session starts being valid (date string or timestamp); defaults to `now`
+ * - `expiryTime`: Time the session expires (date string or timestamp); defaults to `+ 2 hours`
+ * - `timeout`: Activity timeout in seconds (integer or false for none); defaults to `1800` (half an hour)
+ * - `renewable`: Should it be possible to extend the expiry date?; defaults to `true`
*/
public function __construct(Sessions $sessions, $token, array $options)
{
@@ -156,8 +151,8 @@ public function token()
* Gets or sets the transmission mode
* Setting only works for new sessions that haven't been transmitted yet
*
- * @param string $mode Optional new transmission mode
- * @return string Transmission mode
+ * @param string $mode Optional new transmission mode
+ * @return string Transmission mode
*/
public function mode(string $mode = null)
{
@@ -180,7 +175,7 @@ public function mode(string $mode = null)
/**
* Gets the session start time
*
- * @return integer Timestamp
+ * @return int Timestamp
*/
public function startTime(): int
{
@@ -191,8 +186,8 @@ public function startTime(): int
* Gets or sets the session expiry time
* Setting the expiry time also updates the duration and regenerates the session token
*
- * @param string|integer $expiryTime Optional new expiry timestamp or time string to set
- * @return integer Timestamp
+ * @param string|int $expiryTime Optional new expiry timestamp or time string to set
+ * @return int Timestamp
*/
public function expiryTime($expiryTime = null): int
{
@@ -226,8 +221,8 @@ public function expiryTime($expiryTime = null): int
* Gets or sets the session duration
* Setting the duration also updates the expiry time and regenerates the session token
*
- * @param integer $duration Optional new duration in seconds to set
- * @return integer Number of seconds
+ * @param int $duration Optional new duration in seconds to set
+ * @return int Number of seconds
*/
public function duration(int $duration = null): int
{
@@ -252,8 +247,8 @@ public function duration(int $duration = null): int
/**
* Gets or sets the session timeout
*
- * @param integer|false $timeout Optional new timeout to set or false to disable timeout
- * @return integer|false Number of seconds or false for "no timeout"
+ * @param int|false $timeout Optional new timeout to set or false to disable timeout
+ * @return int|false Number of seconds or false for "no timeout"
*/
public function timeout($timeout = null)
{
@@ -288,8 +283,8 @@ public function timeout($timeout = null)
* Gets or sets the renewable flag
* Automatically renews the session if renewing gets enabled
*
- * @param boolean $renewable Optional new renewable flag to set
- * @return boolean
+ * @param bool $renewable Optional new renewable flag to set
+ * @return bool
*/
public function renewable(bool $renewable = null): bool
{
@@ -315,8 +310,8 @@ public function data()
/**
* Magic call method that proxies all calls to session data methods
*
- * @param string $name Method name (one of set, increment, decrement, get, pull, remove, clear)
- * @param array $arguments Method arguments
+ * @param string $name Method name (one of set, increment, decrement, get, pull, remove, clear)
+ * @param array $arguments Method arguments
* @return mixed
*/
public function __call(string $name, array $arguments)
@@ -478,7 +473,7 @@ public function regenerateToken()
* Returns whether the session token needs to be retransmitted to the client
* Only relevant in header and manual modes
*
- * @return boolean
+ * @return bool
*/
public function needsRetransmission(): bool
{
@@ -542,8 +537,8 @@ public function prepareForWriting()
/**
* Parses a token string into its parts and sets them as instance vars
*
- * @param string $token Session token
- * @param bool $withoutKey If true, $token is passed without key
+ * @param string $token Session token
+ * @param bool $withoutKey If true, $token is passed without key
* @return void
*/
protected function parseToken(string $token, bool $withoutKey = false)
@@ -584,9 +579,9 @@ protected function parseToken(string $token, bool $withoutKey = false)
/**
* Makes sure that the given value is a valid timestamp
*
- * @param string|integer $time Timestamp or date string (must be supported by `strtotime()`)
- * @param integer $now Timestamp to use as a base for the calculation of relative dates
- * @return integer Timestamp value
+ * @param string|int $time Timestamp or date string (must be supported by `strtotime()`)
+ * @param int $now Timestamp to use as a base for the calculation of relative dates
+ * @return int Timestamp value
*/
protected static function timeToTimestamp($time, int $now = null): int
{
@@ -762,7 +757,7 @@ protected function autoRenew()
* Checks if the session can be renewed and if the last renewal
* was more than half a session duration ago
*
- * @return boolean
+ * @return bool
*/
protected function needsRenewal(): bool
{
diff --git a/src/Session/SessionData.php b/src/Session/SessionData.php
index 37acaddeee..a6aaf5ed3a 100644
--- a/src/Session/SessionData.php
+++ b/src/Session/SessionData.php
@@ -37,8 +37,8 @@ public function __construct(Session $session, array $data)
/**
* Sets one or multiple session values by key
*
- * @param string|array $key The key to define or a key-value array with multiple values
- * @param mixed $value The value for the passed key (only if one $key is passed)
+ * @param string|array $key The key to define or a key-value array with multiple values
+ * @param mixed $value The value for the passed key (only if one $key is passed)
* @return void
*/
public function set($key, $value = null)
@@ -61,9 +61,9 @@ public function set($key, $value = null)
/**
* Increments one or multiple session values by a specified amount
*
- * @param string|array $key The key to increment or an array with multiple keys
- * @param integer $by Increment by which amount?
- * @param integer $max Maximum amount (value is not incremented further)
+ * @param string|array $key The key to increment or an array with multiple keys
+ * @param int $by Increment by which amount?
+ * @param int $max Maximum amount (value is not incremented further)
* @return void
*/
public function increment($key, int $by = 1, $max = null)
@@ -115,9 +115,9 @@ public function increment($key, int $by = 1, $max = null)
/**
* Decrements one or multiple session values by a specified amount
*
- * @param string|array $key The key to decrement or an array with multiple keys
- * @param integer $by Decrement by which amount?
- * @param integer $min Minimum amount (value is not decremented further)
+ * @param string|array $key The key to decrement or an array with multiple keys
+ * @param int $by Decrement by which amount?
+ * @param int $min Minimum amount (value is not decremented further)
* @return void
*/
public function decrement($key, int $by = 1, $min = null)
@@ -169,8 +169,8 @@ public function decrement($key, int $by = 1, $min = null)
/**
* Returns one or all session values by key
*
- * @param string|null $key The key to get or null for the entire data array
- * @param mixed $default Optional default value to return if the key is not defined
+ * @param string|null $key The key to get or null for the entire data array
+ * @param mixed $default Optional default value to return if the key is not defined
* @return mixed
*/
public function get($key = null, $default = null)
@@ -190,8 +190,8 @@ public function get($key = null, $default = null)
/**
* Retrieves a value and removes it afterwards
*
- * @param string $key The key to get
- * @param mixed $default Optional default value to return if the key is not defined
+ * @param string $key The key to get
+ * @param mixed $default Optional default value to return if the key is not defined
* @return mixed
*/
public function pull(string $key, $default = null)
@@ -208,7 +208,7 @@ public function pull(string $key, $default = null)
/**
* Removes one or multiple session values by key
*
- * @param string|array $key The key to remove or an array with multiple keys
+ * @param string|array $key The key to remove or an array with multiple keys
* @return void
*/
public function remove($key)
@@ -245,7 +245,7 @@ public function clear()
* Reloads the data array with the current session data
* Only used internally
*
- * @param array $data Currently stored session data
+ * @param array $data Currently stored session data
* @return void
*/
public function reload(array $data)
diff --git a/src/Session/SessionStore.php b/src/Session/SessionStore.php
index b916e9a509..a3a96110f3 100644
--- a/src/Session/SessionStore.php
+++ b/src/Session/SessionStore.php
@@ -17,18 +17,18 @@ abstract class SessionStore
* Needs to make sure that the session does not already exist
* and needs to reserve it by locking it exclusively.
*
- * @param int $expiryTime Timestamp
- * @return string Randomly generated session ID (without timestamp)
+ * @param int $expiryTime Timestamp
+ * @return string Randomly generated session ID (without timestamp)
*/
abstract public function createId(int $expiryTime): string;
/**
* Checks if the given session exists
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
- * @return boolean true: session exists,
- * false: session doesn't exist
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
+ * @return bool true: session exists,
+ * false: session doesn't exist
*/
abstract public function exists(int $expiryTime, string $id): bool;
@@ -37,8 +37,8 @@ abstract public function exists(int $expiryTime, string $id): bool;
*
* Needs to throw an Exception on error.
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
* @return void
*/
abstract public function lock(int $expiryTime, string $id);
@@ -48,8 +48,8 @@ abstract public function lock(int $expiryTime, string $id);
*
* Needs to throw an Exception on error.
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
* @return void
*/
abstract public function unlock(int $expiryTime, string $id);
@@ -59,8 +59,8 @@ abstract public function unlock(int $expiryTime, string $id);
*
* Needs to throw an Exception on error.
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
* @return string
*/
abstract public function get(int $expiryTime, string $id): string;
@@ -71,9 +71,9 @@ abstract public function get(int $expiryTime, string $id): string;
* Needs to make sure that the session exists.
* Needs to throw an Exception on error.
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
- * @param string $data Session data to write
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
+ * @param string $data Session data to write
* @return void
*/
abstract public function set(int $expiryTime, string $id, string $data);
@@ -83,8 +83,8 @@ abstract public function set(int $expiryTime, string $id, string $data);
*
* Needs to throw an Exception on error.
*
- * @param int $expiryTime Timestamp
- * @param string $id Session ID
+ * @param int $expiryTime Timestamp
+ * @param string $id Session ID
* @return void
*/
abstract public function destroy(int $expiryTime, string $id);
diff --git a/src/Session/Sessions.php b/src/Session/Sessions.php
index 8f53ce999e..d947080ebb 100644
--- a/src/Session/Sessions.php
+++ b/src/Session/Sessions.php
@@ -30,14 +30,11 @@ class Sessions
/**
* Creates a new Sessions instance
*
- * @param \Kirby\Session\SessionStore|string $store SessionStore object or a path to the storage directory (uses the FileSessionStore)
- * @param array $options Optional additional options:
- * - `mode`: Default token transmission mode (cookie, header or manual)
- * Defaults to `cookie`
- * - `cookieName`: Name to use for the session cookie
- * Defaults to `kirby_session`
- * - `gcInterval`: How often should the garbage collector be run?
- * Integer or `false` for never; defaults to `100`
+ * @param \Kirby\Session\SessionStore|string $store SessionStore object or a path to the storage directory (uses the FileSessionStore)
+ * @param array $options Optional additional options:
+ * - `mode`: Default token transmission mode (cookie, header or manual); defaults to `cookie`
+ * - `cookieName`: Name to use for the session cookie; defaults to `kirby_session`
+ * - `gcInterval`: How often should the garbage collector be run?; integer or `false` for never; defaults to `100`
*/
public function __construct($store, array $options = [])
{
@@ -93,17 +90,12 @@ public function __construct($store, array $options = [])
/**
* Creates a new empty session
*
- * @param array $options Optional additional options:
- * - `mode`: Token transmission mode (cookie or manual)
- * Defaults to default mode of the Sessions instance
- * - `startTime`: Time the session starts being valid (date string or timestamp)
- * Defaults to `now`
- * - `expiryTime`: Time the session expires (date string or timestamp)
- * Defaults to `+ 2 hours`
- * - `timeout`: Activity timeout in seconds (integer or false for none)
- * Defaults to `1800` (half an hour)
- * - `renewable`: Should it be possible to extend the expiry date?
- * Defaults to `true`
+ * @param array $options Optional additional options:
+ * - `mode`: Token transmission mode (cookie or manual); defaults to default mode of the Sessions instance
+ * - `startTime`: Time the session starts being valid (date string or timestamp); defaults to `now`
+ * - `expiryTime`: Time the session expires (date string or timestamp); defaults to `+ 2 hours`
+ * - `timeout`: Activity timeout in seconds (integer or false for none); defaults to `1800` (half an hour)
+ * - `renewable`: Should it be possible to extend the expiry date?; defaults to `true`
* @return \Kirby\Session\Session
*/
public function create(array $options = [])
@@ -119,8 +111,8 @@ public function create(array $options = [])
/**
* Returns the specified Session object
*
- * @param string $token Session token, either including or without the key
- * @param string $mode Optional transmission mode override
+ * @param string $token Session token, either including or without the key
+ * @param string $mode Optional transmission mode override
* @return \Kirby\Session\Session
*/
public function get(string $token, string $mode = null)
diff --git a/src/Text/Markdown.php b/src/Text/Markdown.php
index db3814f65d..98c07c471b 100644
--- a/src/Text/Markdown.php
+++ b/src/Text/Markdown.php
@@ -56,8 +56,8 @@ public function __construct(array $options = [])
/**
* Parses the given text and returns the HTML
*
- * @param string $text
- * @param bool $inline
+ * @param string $text
+ * @param bool $inline
* @return string
*/
public function parse(string $text, bool $inline = false): string
diff --git a/src/Text/SmartyPants.php b/src/Text/SmartyPants.php
index 3c6374aad4..50d70cb9be 100644
--- a/src/Text/SmartyPants.php
+++ b/src/Text/SmartyPants.php
@@ -115,7 +115,7 @@ public function __construct(array $options = [])
/**
* Parses the given text
*
- * @param string $text
+ * @param string $text
* @return string
*/
public function parse(string $text): string
diff --git a/src/Toolkit/A.php b/src/Toolkit/A.php
index ba15bd4df8..9d03da57a4 100644
--- a/src/Toolkit/A.php
+++ b/src/Toolkit/A.php
@@ -51,11 +51,11 @@ public static function append(array $array, array $append): array
* // result: ['cat' => 'miao', 'dog' => 'wuff'];
*
*
- * @param array $array The source array
- * @param mixed $key The key to look for
- * @param mixed $default Optional default value, which should be
- * returned if no element has been found
- * @return mixed
+ * @param array $array The source array
+ * @param mixed $key The key to look for
+ * @param mixed $default Optional default value, which should be
+ * returned if no element has been found
+ * @return mixed
*/
public static function get($array, $key, $default = null)
{
@@ -130,12 +130,12 @@ public static function join($value, $separator = ', ')
/**
* Merges arrays recursively
*
- * @param array $array1
- * @param array $array2
- * @param boolean $mode Behavior for elements with numeric keys;
- * A::MERGE_APPEND: elements are appended, keys are reset;
- * A::MERGE_OVERWRITE: elements are overwritten, keys are preserved
- * A::MERGE_REPLACE: non-associative arrays are completely replaced
+ * @param array $array1
+ * @param array $array2
+ * @param bool $mode Behavior for elements with numeric keys;
+ * A::MERGE_APPEND: elements are appended, keys are reset;
+ * A::MERGE_OVERWRITE: elements are overwritten, keys are preserved
+ * A::MERGE_REPLACE: non-associative arrays are completely replaced
* @return array
*/
public static function merge($array1, $array2, $mode = A::MERGE_APPEND)
@@ -196,10 +196,10 @@ public static function merge($array1, $array2, $mode = A::MERGE_APPEND)
* // result: ['homer', 'marge', 'lisa'];
*
*
- * @param array $array The source array
- * @param string $key The key name of the column to extract
- * @return array The result array with all values
- * from that column.
+ * @param array $array The source array
+ * @param string $key The key name of the column to extract
+ * @return array The result array with all values
+ * from that column.
*/
public static function pluck(array $array, string $key)
{
@@ -243,8 +243,8 @@ public static function prepend(array $array, array $prepend): array
* // ];
*
*
- * @param array $array The source array
- * @return array The shuffled result array
+ * @param array $array The source array
+ * @return array The shuffled result array
*/
public static function shuffle(array $array): array
{
@@ -275,8 +275,8 @@ public static function shuffle(array $array): array
* // first: 'miao'
*
*
- * @param array $array The source array
- * @return mixed The first element
+ * @param array $array The source array
+ * @return mixed The first element
*/
public static function first(array $array)
{
@@ -297,8 +297,8 @@ public static function first(array $array)
* // last: 'tweet'
*
*
- * @param array $array The source array
- * @return mixed The last element
+ * @param array $array The source array
+ * @return mixed The last element
*/
public static function last(array $array)
{
@@ -326,12 +326,12 @@ public static function last(array $array)
* // ];
*
*
- * @param array $array The source array
- * @param int $limit The number of elements the array should
- * contain after filling it up.
- * @param mixed $fill The element, which should be used to
- * fill the array
- * @return array The filled-up result array
+ * @param array $array The source array
+ * @param int $limit The number of elements the array should
+ * contain after filling it up.
+ * @param mixed $fill The element, which should be used to
+ * fill the array
+ * @return array The filled-up result array
*/
public static function fill(array $array, int $limit, $fill = 'placeholder'): array
{
@@ -394,10 +394,10 @@ public static function move(array $array, int $from, int $to): array
* // ];
*
*
- * @param array $array The source array
- * @param array $required An array of required keys
- * @return array An array of missing fields. If this
- * is empty, nothing is missing.
+ * @param array $array The source array
+ * @param array $required An array of required keys
+ * @return array An array of missing fields. If this
+ * is empty, nothing is missing.
*/
public static function missing(array $array, array $required = []): array
{
@@ -451,13 +451,13 @@ public static function missing(array $array, array $required = []): array
*
*
*
- * @param array $array The source array
- * @param string $field The name of the column
- * @param string $direction desc (descending) or asc (ascending)
- * @param int $method A PHP sort method flag or 'natural' for
- * natural sorting, which is not supported in
- * PHP by sort flags
- * @return array The sorted array
+ * @param array $array The source array
+ * @param string $field The name of the column
+ * @param string $direction desc (descending) or asc (ascending)
+ * @param int $method A PHP sort method flag or 'natural' for
+ * natural sorting, which is not supported in
+ * PHP by sort flags
+ * @return array The sorted array
*/
public static function sort(array $array, string $field, string $direction = 'desc', $method = SORT_REGULAR): array
{
@@ -500,8 +500,8 @@ public static function sort(array $array, string $field, string $direction = 'de
* // returns: true
*
*
- * @param array $array The array to analyze
- * @return boolean true: The array is associative false: It's not
+ * @param array $array The array to analyze
+ * @return bool true: The array is associative false: It's not
*/
public static function isAssociative(array $array): bool
{
@@ -511,9 +511,9 @@ public static function isAssociative(array $array): bool
/**
* Returns the average value of an array
*
- * @param array $array The source array
- * @param int $decimals The number of decimals to return
- * @return float The average value
+ * @param array $array The source array
+ * @param int $decimals The number of decimals to return
+ * @return float The average value
*/
public static function average(array $array, int $decimals = 0): float
{
@@ -568,8 +568,8 @@ public static function extend(...$arrays): array
* ]);
*
*
- * @param array $array
- * @param array $update
+ * @param array $array
+ * @param array $update
* @return array
*/
public static function update(array $array, array $update): array
diff --git a/src/Toolkit/Collection.php b/src/Toolkit/Collection.php
index 68c511421d..1c9b29a172 100644
--- a/src/Toolkit/Collection.php
+++ b/src/Toolkit/Collection.php
@@ -35,8 +35,8 @@ class Collection extends Iterator implements Countable
/**
* Magic getter function
*
- * @param string $key
- * @param mixed $arguments
+ * @param string $key
+ * @param mixed $arguments
* @return mixed
*/
public function __call(string $key, $arguments)
@@ -67,7 +67,7 @@ public function __debugInfo(): array
/**
* Low-level getter for elements
*
- * @param mixed $key
+ * @param mixed $key
* @return mixed
*/
public function __get($key)
@@ -82,8 +82,8 @@ public function __get($key)
/**
* Low-level setter for elements
*
- * @param string $key string or array
- * @param mixed $value
+ * @param string $key string or array
+ * @param mixed $value
*/
public function __set(string $key, $value)
{
@@ -114,8 +114,8 @@ public function __unset($key)
/**
* Appends an element
*
- * @param mixed $key
- * @param mixed $item
+ * @param mixed $key
+ * @param mixed $item
* @return \Kirby\Toolkit\Collection
*/
public function append(...$args)
@@ -133,9 +133,9 @@ public function append(...$args)
* Creates chunks of the same size.
* The last chunk may be smaller
*
- * @param int $size Number of elements per chunk
- * @return \Kirby\Toolkit\Collection A new collection with an element for each chunk and
- * a sub collection in each chunk
+ * @param int $size Number of elements per chunk
+ * @return \Kirby\Toolkit\Collection A new collection with an element for each chunk and
+ * a sub collection in each chunk
*/
public function chunk(int $size)
{
@@ -175,7 +175,7 @@ public function clone()
/**
* Getter and setter for the data
*
- * @param array $data
+ * @param array $data
* @return array|Collection
*/
public function data(array $data = null)
@@ -422,8 +422,8 @@ public function flip()
/**
* Getter
*
- * @param mixed $key
- * @param mixed $default
+ * @param mixed $key
+ * @param mixed $default
* @return mixed
*/
public function get($key, $default = null)
@@ -439,7 +439,7 @@ public function get($key, $default = null)
*
* @param array|object $item
* @param string $attribute
- * @param boolean $split
+ * @param bool $split
* @param mixed $related
* @return mixed
*/
@@ -542,10 +542,38 @@ public function groupBy($field, bool $i = true)
});
}
+ /**
+ * Returns a Collection with the intersection of the given elements
+ *
+ * @param \Kirby\Toolkit\Collection $other
+ * @return \Kirby\Toolkit\Collection
+ */
+ public function intersection($other)
+ {
+ return $other->find($this->keys());
+ }
+
+ /**
+ * Checks if there is an intersection between the given collection and this collection
+ *
+ * @param \Kirby\Toolkit\Collection $other
+ * @return bool
+ */
+ public function intersects($other): bool
+ {
+ foreach ($this->keys() as $key) {
+ if ($other->has($key)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/**
* Checks if the number of elements is zero
*
- * @return boolean
+ * @return bool
*/
public function isEmpty(): bool
{
@@ -555,7 +583,7 @@ public function isEmpty(): bool
/**
* Checks if the number of elements is even
*
- * @return boolean
+ * @return bool
*/
public function isEven(): bool
{
@@ -565,7 +593,7 @@ public function isEven(): bool
/**
* Checks if the number of elements is more than zero
*
- * @return boolean
+ * @return bool
*/
public function isNotEmpty(): bool
{
@@ -575,7 +603,7 @@ public function isNotEmpty(): bool
/**
* Checks if the number of elements is odd
*
- * @return boolean
+ * @return bool
*/
public function isOdd(): bool
{
@@ -596,7 +624,7 @@ public function last()
/**
* Returns a new object with a limited number of elements
*
- * @param int $limit The number of elements to return
+ * @param int $limit The number of elements to return
* @return \Kirby\Toolkit\Collection
*/
public function limit(int $limit)
@@ -607,7 +635,7 @@ public function limit(int $limit)
/**
* Map a function to each element
*
- * @param callable $callback
+ * @param callable $callback
* @return \Kirby\Toolkit\Collection
*/
public function map(callable $callback)
@@ -619,7 +647,7 @@ public function map(callable $callback)
/**
* Returns the nth element from the collection
*
- * @param integer $n
+ * @param int $n
* @return mixed
*/
public function nth(int $n)
@@ -645,7 +673,7 @@ public function not(...$keys)
/**
* Returns a new object starting from the given offset
*
- * @param int $offset The index to start from
+ * @param int $offset The index to start from
* @return \Kirby\Toolkit\Collection
*/
public function offset(int $offset)
@@ -710,8 +738,8 @@ public function pluck(string $field, string $split = null, bool $unique = false)
/**
* Prepends an element to the data array
*
- * @param mixed $key
- * @param mixed $item
+ * @param mixed $key
+ * @param mixed $item
* @return self
*/
public function prepend(...$args)
@@ -790,8 +818,8 @@ public function remove($key)
/**
* Adds a new element to the collection
*
- * @param mixed $key string or array
- * @param mixed $value
+ * @param mixed $key string or array
+ * @param mixed $value
* @return self
*/
public function set($key, $value = null)
@@ -830,8 +858,8 @@ public function shuffle()
/**
* Returns a slice of the object
*
- * @param int $offset The optional index to start the slice from
- * @param int $limit The optional number of elements to return
+ * @param int $offset The optional index to start the slice from
+ * @param int $limit The optional number of elements to return
* @return \Kirby\Toolkit\Collection
*/
public function slice(int $offset = 0, int $limit = null)
@@ -868,10 +896,10 @@ public static function sortArgs(string $sortBy): array
/**
* Sorts the elements by any number of fields
*
- * @param $field string|callable Field name or value callback to sort by
- * @param $direction string asc or desc
- * @param $method int The sort flag, SORT_REGULAR, SORT_NUMERIC etc.
- * @return Collection
+ * @param string|callable $field Field name or value callback to sort by
+ * @param string $direction asc or desc
+ * @param int $method The sort flag, SORT_REGULAR, SORT_NUMERIC etc.
+ * @return Collection
*/
public function sortBy()
{
@@ -1027,10 +1055,34 @@ public function values(): array
return array_values($this->data);
}
+ /**
+ * The when method only executes the given Closure when the first parameter
+ * is true. If the first parameter is false, the Closure will not be executed.
+ * You may pass another Closure as the third parameter to the when method.
+ * This Closure will execute if the first parameter evaluates as false
+ *
+ * @param mixed $condition
+ * @param Closure $callback
+ * @param Closure $fallback
+ * @return mixed
+ */
+ public function when($condition, Closure $callback, Closure $fallback = null)
+ {
+ if ($condition) {
+ return $callback->call($this, $condition);
+ }
+
+ if ($fallback !== null) {
+ return $fallback->call($this, $condition);
+ }
+
+ return $this;
+ }
+
/**
* Alias for $this->not()
*
- * @param string ...$keys any number of keys, passed as individual arguments
+ * @param string ...$keys any number of keys, passed as individual arguments
* @return \Kirby\Toolkit\Collection
*/
public function without(...$keys)
diff --git a/src/Toolkit/Dir.php b/src/Toolkit/Dir.php
index e8ba48d865..f079b0c115 100644
--- a/src/Toolkit/Dir.php
+++ b/src/Toolkit/Dir.php
@@ -149,7 +149,7 @@ public static function index(string $dir, bool $recursive = false, array $ignore
* Checks if the folder has any contents
*
* @param string $dir
- * @return boolean
+ * @return bool
*/
public static function isEmpty(string $dir): bool
{
@@ -160,7 +160,7 @@ public static function isEmpty(string $dir): bool
* Checks if the directory is readable
*
* @param string $dir
- * @return boolean
+ * @return bool
*/
public static function isReadable(string $dir): bool
{
@@ -171,7 +171,7 @@ public static function isReadable(string $dir): bool
* Checks if the directory is writable
*
* @param string $dir
- * @return boolean
+ * @return bool
*/
public static function isWritable(string $dir): bool
{
@@ -183,7 +183,7 @@ public static function isWritable(string $dir): bool
*
* @param string $source
* @param string $link
- * @return boolean
+ * @return bool
*/
public static function link(string $source, string $link): bool
{
@@ -207,9 +207,9 @@ public static function link(string $source, string $link): bool
/**
* Creates a new directory
*
- * @param string $dir The path for the new directory
- * @param boolean $recursive Create all parent directories, which don't exist
- * @return boolean True: the dir has been created, false: creating failed
+ * @param string $dir The path for the new directory
+ * @param bool $recursive Create all parent directories, which don't exist
+ * @return bool True: the dir has been created, false: creating failed
*/
public static function make(string $dir, bool $recursive = true): bool
{
@@ -240,10 +240,10 @@ public static function make(string $dir, bool $recursive = true): bool
* Recursively check when the dir and all
* subfolders have been modified for the last time.
*
- * @param string $dir The path of the directory
- * @param string $format
- * @param string $handler
- * @return int
+ * @param string $dir The path of the directory
+ * @param string $format
+ * @param string $handler
+ * @return int
*/
public static function modified(string $dir, string $format = null, string $handler = 'date')
{
@@ -266,9 +266,9 @@ public static function modified(string $dir, string $format = null, string $hand
/**
* Moves a directory to a new location
*
- * @param string $old The current path of the directory
- * @param string $new The desired path where the dir should be moved to
- * @return boolean true: the directory has been moved, false: moving failed
+ * @param string $old The current path of the directory
+ * @param string $new The desired path where the dir should be moved to
+ * @return bool true: the directory has been moved, false: moving failed
*/
public static function move(string $old, string $new): bool
{
@@ -302,10 +302,10 @@ public static function niceSize(string $dir)
* Reads all files from a directory and returns them as an array.
* It skips unwanted invisible stuff.
*
- * @param string $dir The path of directory
- * @param array $ignore Optional array with filenames, which should be ignored
- * @param bool $absolute If true, the full path for each item will be returned
- * @return array An array of filenames
+ * @param string $dir The path of directory
+ * @param array $ignore Optional array with filenames, which should be ignored
+ * @param bool $absolute If true, the full path for each item will be returned
+ * @return array An array of filenames
*/
public static function read(string $dir, array $ignore = null, bool $absolute = false): array
{
@@ -334,7 +334,7 @@ public static function read(string $dir, array $ignore = null, bool $absolute =
* Removes a folder including all containing files and folders
*
* @param string $dir
- * @return boolean
+ * @return bool
*/
public static function remove(string $dir): bool
{
@@ -370,8 +370,8 @@ public static function remove(string $dir): bool
/**
* Gets the size of the directory and all subfolders and files
*
- * @param string $dir The path of the directory
- * @return mixed
+ * @param string $dir The path of the directory
+ * @return mixed
*/
public static function size(string $dir)
{
diff --git a/src/Toolkit/Escape.php b/src/Toolkit/Escape.php
index 0a156764f5..9647696669 100644
--- a/src/Toolkit/Escape.php
+++ b/src/Toolkit/Escape.php
@@ -38,7 +38,7 @@ class Escape
* content
* content
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function attr($string)
@@ -59,7 +59,7 @@ public static function attr($string)
*
* text
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function css($string)
@@ -79,7 +79,7 @@ public static function css($string)
* ...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...
* ...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function html($string)
@@ -97,7 +97,7 @@ public static function html($string)
*
*
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function js($string)
@@ -113,7 +113,7 @@ public static function js($string)
*
* link
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function url($string)
@@ -135,7 +135,7 @@ public static function url($string)
* < is replaced with <
* > is replaced with >
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function xml($string)
diff --git a/src/Toolkit/F.php b/src/Toolkit/F.php
index d959339b8f..79efb74138 100644
--- a/src/Toolkit/F.php
+++ b/src/Toolkit/F.php
@@ -108,9 +108,9 @@ class F
/**
* Appends new content to an existing file
*
- * @param string $file The path for the file
- * @param mixed $content Either a string or an array. Arrays will be converted to JSON.
- * @return boolean
+ * @param string $file The path for the file
+ * @param mixed $content Either a string or an array. Arrays will be converted to JSON.
+ * @return bool
*/
public static function append(string $file, $content): bool
{
@@ -131,10 +131,10 @@ public static function base64(string $file): string
/**
* Copy a file to a new location.
*
- * @param string $source
- * @param string $target
- * @param boolean $force
- * @return boolean
+ * @param string $source
+ * @param string $target
+ * @param bool $force
+ * @return bool
*/
public static function copy(string $source, string $target, bool $force = false): bool
{
@@ -162,7 +162,7 @@ public static function copy(string $source, string $target, bool $force = false)
*
*
*
- * @param string $file The path
+ * @param string $file The path
* @return string
*/
public static function dirname(string $file): string
@@ -175,7 +175,7 @@ public static function dirname(string $file): string
*
* @param string $file
* @param string $in
- * @return boolean
+ * @return bool
*/
public static function exists(string $file, string $in = null): bool
{
@@ -190,8 +190,8 @@ public static function exists(string $file, string $in = null): bool
/**
* Gets the extension of a file
*
- * @param string $file The filename or path
- * @param string $extension Set an optional extension to overwrite the current one
+ * @param string $file The filename or path
+ * @param string $extension Set an optional extension to overwrite the current one
* @return string
*/
public static function extension(string $file = null, string $extension = null): string
@@ -258,7 +258,7 @@ public static function extensions(string $type = null)
*
*
*
- * @param string $name The path
+ * @param string $name The path
* @return string
*/
public static function filename(string $name): string
@@ -269,8 +269,8 @@ public static function filename(string $name): string
/**
* Invalidate opcode cache for file.
*
- * @param string $file The path of the file
- * @return boolean
+ * @param string $file The path of the file
+ * @return bool
*/
public static function invalidateOpcodeCache(string $file): bool
{
@@ -286,7 +286,7 @@ public static function invalidateOpcodeCache(string $file): bool
*
* @param string $file Full path to the file
* @param string $value An extension or mime type
- * @return boolean
+ * @return bool
*/
public static function is(string $file, string $value): bool
{
@@ -307,7 +307,7 @@ public static function is(string $file, string $value): bool
* Checks if the file is readable
*
* @param string $file
- * @return boolean
+ * @return bool
*/
public static function isReadable(string $file): bool
{
@@ -318,7 +318,7 @@ public static function isReadable(string $file): bool
* Checks if the file is writable
*
* @param string $file
- * @return boolean
+ * @return bool
*/
public static function isWritable(string $file): bool
{
@@ -335,7 +335,7 @@ public static function isWritable(string $file): bool
* @param string $source
* @param string $link
* @param string $method
- * @return boolean
+ * @return bool
*/
public static function link(string $source, string $link, string $method = 'link'): bool
{
@@ -414,9 +414,9 @@ public static function mimeToType(string $mime)
/**
* Get the file's last modification time.
*
- * @param string $file
- * @param string $format
- * @param string $handler date or strftime
+ * @param string $file
+ * @param string $format
+ * @param string $handler date or strftime
* @return mixed
*/
public static function modified(string $file, string $format = null, string $handler = 'date')
@@ -440,10 +440,10 @@ public static function modified(string $file, string $format = null, string $han
/**
* Moves a file to a new location
*
- * @param string $oldRoot The current path for the file
- * @param string $newRoot The path to the new location
- * @param boolean $force Force move if the target file exists
- * @return boolean
+ * @param string $oldRoot The current path for the file
+ * @param string $newRoot The path to the new location
+ * @param bool $force Force move if the target file exists
+ * @return bool
*/
public static function move(string $oldRoot, string $newRoot, bool $force = false): bool
{
@@ -472,7 +472,7 @@ public static function move(string $oldRoot, string $newRoot, bool $force = fals
/**
* Extracts the name from a file path or filename without extension
*
- * @param string $name The path or filename
+ * @param string $name The path or filename
* @return string
*/
public static function name(string $name): string
@@ -483,7 +483,7 @@ public static function name(string $name): string
/**
* Converts an integer size into a human readable format
*
- * @param mixed $size The file size or a file path
+ * @param mixed $size The file size or a file path
* @return string|int
*/
public static function niceSize($size): string
@@ -508,7 +508,7 @@ public static function niceSize($size): string
/**
* Reads the content of a file
*
- * @param string $file The path for the file
+ * @param string $file The path for the file
* @return string|false
*/
public static function read(string $file)
@@ -520,9 +520,9 @@ public static function read(string $file)
* Changes the name of the file without
* touching the extension
*
- * @param string $file
- * @param string $newName
- * @param bool $overwrite Force overwrite existing files
+ * @param string $file
+ * @param string $newName
+ * @param bool $overwrite Force overwrite existing files
* @return string|false
*/
public static function rename(string $file, string $newName, bool $overwrite = false)
@@ -610,8 +610,8 @@ public static function relativepath(string $file, string $in = null): string
*
*
*
- * @param string $file The path for the file
- * @return boolean
+ * @param string $file The path for the file
+ * @return bool
*/
public static function remove(string $file): bool
{
@@ -642,7 +642,7 @@ public static function remove(string $file): bool
*
*
*
- * @param string $string The file name
+ * @param string $string The file name
* @return string
*/
public static function safeName(string $string): string
@@ -675,7 +675,7 @@ public static function similar(string $path, string $pattern = '*'): array
/**
* Returns the size of a file.
*
- * @param mixed $file The path
+ * @param mixed $file The path
* @return int
*/
public static function size(string $file): int
@@ -728,7 +728,7 @@ public static function type(string $file)
*
* @param string $file
* @param string $to
- * @return boolean
+ * @return bool
*/
public static function unzip(string $file, string $to): bool
{
@@ -765,10 +765,10 @@ public static function uri(string $file)
/**
* Creates a new file
*
- * @param string $file The path for the new file
- * @param mixed $content Either a string, an object or an array. Arrays and objects will be serialized.
- * @param boolean $append true: append the content to an exisiting file if available. false: overwrite.
- * @return boolean
+ * @param string $file The path for the new file
+ * @param mixed $content Either a string, an object or an array. Arrays and objects will be serialized.
+ * @param bool $append true: append the content to an exisiting file if available. false: overwrite.
+ * @return bool
*/
public static function write(string $file, $content, bool $append = false): bool
{
diff --git a/src/Toolkit/File.php b/src/Toolkit/File.php
index 857a416c31..4a4ac900bf 100644
--- a/src/Toolkit/File.php
+++ b/src/Toolkit/File.php
@@ -56,8 +56,8 @@ public function base64(): string
/**
* Copy a file to a new location.
*
- * @param string $target
- * @param boolean $force
+ * @param string $target
+ * @param bool $force
* @return self
*/
public function copy(string $target, bool $force = false)
@@ -147,7 +147,7 @@ public function is(string $value): bool
/**
* Checks if the file is readable
*
- * @return boolean
+ * @return bool
*/
public function isReadable(): bool
{
@@ -157,7 +157,7 @@ public function isReadable(): bool
/**
* Checks if the file is writable
*
- * @return boolean
+ * @return bool
*/
public function isWritable(): bool
{
@@ -177,8 +177,8 @@ public function mime()
/**
* Get the file's last modification time.
*
- * @param string $format
- * @param string $handler date or strftime
+ * @param string $format
+ * @param string $handler date or strftime
* @return mixed
*/
public function modified(string $format = null, string $handler = 'date')
@@ -189,8 +189,8 @@ public function modified(string $format = null, string $handler = 'date')
/**
* Move the file to a new location
*
- * @param string $newRoot
- * @param bool $overwrite Force overwriting any existing files
+ * @param string $newRoot
+ * @param bool $overwrite Force overwriting any existing files
* @return self
*/
public function move(string $newRoot, bool $overwrite = false)
@@ -248,8 +248,8 @@ public function realpath(): string
* Changes the name of the file without
* touching the extension
*
- * @param string $newName
- * @param bool $overwrite Force overwrite existing files
+ * @param string $newName
+ * @param bool $overwrite Force overwrite existing files
* @return self
*/
public function rename(string $newName, bool $overwrite = false)
@@ -276,7 +276,7 @@ public function root(): ?string
/**
* Returns the raw size of the file
*
- * @return int
+ * @return int
*/
public function size(): int
{
@@ -321,7 +321,7 @@ public function type()
/**
* Writes content to the file
*
- * @param string $content
+ * @param string $content
* @return bool
*/
public function write($content): bool
diff --git a/src/Toolkit/Html.php b/src/Toolkit/Html.php
index 02cfad2893..de0b535a64 100644
--- a/src/Toolkit/Html.php
+++ b/src/Toolkit/Html.php
@@ -144,8 +144,8 @@ public static function breaks(string $string = null): string
*
*
*
- * @param string $string
- * @return string The html string
+ * @param string $string
+ * @return string The html string
*/
public static function decode(string $string = null): string
{
@@ -189,9 +189,9 @@ public static function email(string $email, $text = null, array $attr = []): str
/**
* Converts a string to a html-safe string
*
- * @param string $string
- * @param bool $keepTags
- * @return string The html string
+ * @param string $string
+ * @param bool $keepTags
+ * @return string The html string
*/
public static function encode(string $string = null, bool $keepTags = false): string
{
@@ -465,7 +465,7 @@ public static function vimeo(string $url, ?array $options = [], array $attr = []
}
// build the options query
- if (!empty($options)) {
+ if (empty($options) === false) {
$query = '?' . http_build_query($options);
} else {
$query = '';
@@ -523,7 +523,7 @@ public static function youtube(string $url, ?array $options = [], array $attr =
}
// build the options query
- if (!empty($options)) {
+ if (empty($options) === false) {
$query = '?' . http_build_query($options);
} else {
$query = '';
diff --git a/src/Toolkit/I18n.php b/src/Toolkit/I18n.php
index 97a2dd258c..8e44cdfda6 100644
--- a/src/Toolkit/I18n.php
+++ b/src/Toolkit/I18n.php
@@ -67,7 +67,7 @@ public static function fallback(): string
* depending on the given number
*
* @param int $count
- * @param boolean $none If true, 'none' will be returned if the count is 0
+ * @param bool $none If true, 'none' will be returned if the count is 0
* @return string
*/
public static function form(int $count, bool $none = false): string
@@ -194,7 +194,7 @@ public static function translations(): array
* Translate amounts
*
* @param string $key
- * @param integer $count
+ * @param int $count
* @param string $locale
* @return mixed
*/
diff --git a/src/Toolkit/Iterator.php b/src/Toolkit/Iterator.php
index a39e156b7f..81fb2aece4 100644
--- a/src/Toolkit/Iterator.php
+++ b/src/Toolkit/Iterator.php
@@ -2,6 +2,9 @@
namespace Kirby\Toolkit;
+use ArrayIterator;
+use IteratorAggregate;
+
/**
* Extended version of PHP's iterator
* class that builds the foundation of our
@@ -13,7 +16,7 @@
* @copyright Bastian Allgeier GmbH
* @license https://opensource.org/licenses/MIT
*/
-class Iterator implements \Iterator
+class Iterator implements IteratorAggregate
{
/**
* The data array
@@ -32,6 +35,16 @@ public function __construct(array $data = [])
$this->data = $data;
}
+ /**
+ * Get an iterator for the items.
+ *
+ * @return \ArrayIterator
+ */
+ public function getIterator()
+ {
+ return new ArrayIterator($this->data);
+ }
+
/**
* Returns the current key
*
@@ -95,7 +108,7 @@ public function rewind()
/**
* Checks if the current element is valid
*
- * @return boolean
+ * @return bool
*/
public function valid(): bool
{
@@ -115,8 +128,8 @@ public function count(): int
/**
* Tries to find the index number for the given element
*
- * @param mixed $needle the element to search for
- * @return string|false the name of the key or false
+ * @param mixed $needle the element to search for
+ * @return string|false the name of the key or false
*/
public function indexOf($needle)
{
@@ -126,8 +139,8 @@ public function indexOf($needle)
/**
* Tries to find the key for the given element
*
- * @param mixed $needle the element to search for
- * @return string|false the name of the key or false
+ * @param mixed $needle the element to search for
+ * @return string|false the name of the key or false
*/
public function keyOf($needle)
{
@@ -137,8 +150,8 @@ public function keyOf($needle)
/**
* Checks by key if an element is included
*
- * @param mixed $key
- * @return boolean
+ * @param mixed $key
+ * @return bool
*/
public function has($key): bool
{
@@ -148,8 +161,8 @@ public function has($key): bool
/**
* Checks if the current key is set
*
- * @param mixed $key the key to check
- * @return boolean
+ * @param mixed $key the key to check
+ * @return bool
*/
public function __isset($key): bool
{
diff --git a/src/Toolkit/Mime.php b/src/Toolkit/Mime.php
index 93f044d726..7c26bb5042 100644
--- a/src/Toolkit/Mime.php
+++ b/src/Toolkit/Mime.php
@@ -6,7 +6,7 @@
/**
* The `Mime` class provides method
- * for mime type detection or guessing
+ * for MIME type detection or guessing
* from different criteria like
* extensions etc.
*
@@ -19,7 +19,7 @@
class Mime
{
/**
- * Extension to mime type map
+ * Extension to MIME type map
*
* @var array
*/
@@ -112,7 +112,7 @@ class Mime
];
/**
- * Fixes an invalid mime type guess for the given file
+ * Fixes an invalid MIME type guess for the given file
*
* @param string $file
* @param string $mime
@@ -153,7 +153,7 @@ public static function fix(string $file, string $mime = null, string $extension
}
/**
- * Guesses a mime type by extension
+ * Guesses a MIME type by extension
*
* @param string $extension
* @return string|null
@@ -165,7 +165,7 @@ public static function fromExtension(string $extension)
}
/**
- * Returns the mime type of a file
+ * Returns the MIME type of a file
*
* @param string $file
* @return string|false
@@ -183,7 +183,7 @@ public static function fromFileInfo(string $file)
}
/**
- * Returns the mime type of a file
+ * Returns the MIME type of a file
*
* @param string $file
* @return string|false
@@ -198,7 +198,7 @@ public static function fromMimeContentType(string $file)
}
/**
- * Tries to detect a valid SVG and returns the mime type accordingly
+ * Tries to detect a valid SVG and returns the MIME type accordingly
*
* @param string $file
* @return string|false
@@ -219,18 +219,19 @@ public static function fromSvg(string $file)
}
/**
- * Undocumented function
+ * Tests if a given MIME type is matched by an `Accept` header
+ * pattern; returns true if the MIME type is contained at all
*
* @param string $mime
* @param string $pattern
- * @return boolean
+ * @return bool
*/
public static function isAccepted(string $mime, string $pattern): bool
{
$accepted = Str::accepted($pattern);
foreach ($accepted as $m) {
- if (fnmatch($m['value'], $mime, FNM_PATHNAME) === true) {
+ if (static::matches($mime, $m['value']) === true) {
return true;
}
}
@@ -239,7 +240,20 @@ public static function isAccepted(string $mime, string $pattern): bool
}
/**
- * Returns the extension for a given mime type
+ * Tests if a MIME wildcard pattern from an `Accept` header
+ * matches a given type
+ *
+ * @param string $test
+ * @param string $wildcard
+ * @return bool
+ */
+ public static function matches(string $test, string $wildcard): bool
+ {
+ return fnmatch($wildcard, $test, FNM_PATHNAME) === true;
+ }
+
+ /**
+ * Returns the extension for a given MIME type
*
* @param string|null $mime
* @return string|false
@@ -260,7 +274,7 @@ public static function toExtension(string $mime = null)
}
/**
- * Returns all available extensions for a given mime type
+ * Returns all available extensions for a given MIME type
*
* @param string|null $mime
* @return array
@@ -285,7 +299,7 @@ public static function toExtensions(string $mime = null): array
}
/**
- * Returns the mime type of a file
+ * Returns the MIME type of a file
*
* @param string $file
* @param string $extension
@@ -314,7 +328,7 @@ public static function type(string $file, string $extension = null)
}
/**
- * Returns all detectable mime types
+ * Returns all detectable MIME types
*
* @return array
*/
diff --git a/src/Toolkit/Pagination.php b/src/Toolkit/Pagination.php
index b23210ecad..bcb47f56c0 100644
--- a/src/Toolkit/Pagination.php
+++ b/src/Toolkit/Pagination.php
@@ -2,7 +2,8 @@
namespace Kirby\Toolkit;
-use Exception;
+use Kirby\Exception\ErrorPageException;
+use Kirby\Exception\Exception;
/**
* Basic pagination handling
@@ -15,38 +16,48 @@
*/
class Pagination
{
+ use Properties {
+ setProperties as protected baseSetProperties;
+ }
+
/**
* The current page
*
- * @var integer
+ * @var int
*/
protected $page;
/**
* Total number of items
*
- * @var integer
+ * @var int
*/
- protected $total;
+ protected $total = 0;
/**
* The number of items per page
*
- * @var integer
+ * @var int
+ */
+ protected $limit = 20;
+
+ /**
+ * Whether validation of the pagination page
+ * is enabled; will throw Exceptions if true
+ *
+ * @var bool
*/
- protected $limit;
+ public static $validate = true;
/**
* Creates a new pagination object
* with the given parameters
*
- * @param array $params
+ * @param array $props
*/
- public function __construct(array $params = [])
+ public function __construct(array $props = [])
{
- $this->page($params['page'] ?? 1);
- $this->limit($params['limit'] ?? 20);
- $this->total($params['total'] ?? 0);
+ $this->setProperties($props);
}
/**
@@ -113,67 +124,48 @@ public static function for(Collection $collection, ...$arguments)
}
/**
- * Getter and setter for the current page
+ * Getter for the current page
*
- * @param int|null $page
- * @return int|\Kirby\Toolkit\Pagination
+ * @deprecated 3.3.0 Setter is no longer supported, use $pagination->clone()
+ * @return int
*/
- public function page(int $page = null)
+ public function page(int $page = null): int
{
- if ($page === null) {
- if ($this->page > $this->pages()) {
- $this->page = $this->lastPage();
- }
-
- if ($this->page < 1) {
- $this->page = $this->firstPage();
- }
-
- return $this->page;
+ if ($page !== null) {
+ throw new Exception('$pagination->page() setter is no longer supported, use $pagination->clone()'); // @codeCoverageIgnore
}
- $this->page = $page;
- return $this;
+ return $this->page;
}
/**
- * Getter and setter for the total number of items
+ * Getter for the total number of items
*
- * @param int|null $total
- * @return int|\Kirby\Toolkit\Pagination
+ * @deprecated 3.3.0 Setter is no longer supported, use $pagination->clone()
+ * @return int
*/
- public function total(int $total = null)
+ public function total(int $total = null): int
{
- if ($total === null) {
- return $this->total;
- }
-
- if ($total < 0) {
- throw new Exception('Invalid total number of items: ' . $total);
+ if ($total !== null) {
+ throw new Exception('$pagination->total() setter is no longer supported, use $pagination->clone()'); // @codeCoverageIgnore
}
- $this->total = $total;
- return $this;
+ return $this->total;
}
/**
- * Getter and setter for the number of items per page
+ * Getter for the number of items per page
*
- * @param int|null $limit
- * @return int|\Kirby\Toolkit\Pagination
+ * @deprecated 3.3.0 Setter is no longer supported, use $pagination->clone()
+ * @return int
*/
- public function limit(int $limit = null)
+ public function limit(int $limit = null): int
{
- if ($limit === null) {
- return $this->limit;
+ if ($limit !== null) {
+ throw new Exception('$pagination->limit() setter is no longer supported, use $pagination->clone()'); // @codeCoverageIgnore
}
- if ($limit < 1) {
- throw new Exception('Invalid pagination limit: ' . $limit);
- }
-
- $this->limit = $limit;
- return $this;
+ return $this->limit;
}
/**
@@ -256,7 +248,7 @@ public function offset(): int
* Checks if the given page exists
*
* @param int $page
- * @return boolean
+ * @return bool
*/
public function hasPage(int $page): bool
{
@@ -274,7 +266,7 @@ public function hasPage(int $page): bool
/**
* Checks if there are any pages at all
*
- * @return boolean
+ * @return bool
*/
public function hasPages(): bool
{
@@ -284,7 +276,7 @@ public function hasPages(): bool
/**
* Checks if there's a previous page
*
- * @return boolean
+ * @return bool
*/
public function hasPrevPage(): bool
{
@@ -304,7 +296,7 @@ public function prevPage()
/**
* Checks if there's a next page
*
- * @return boolean
+ * @return bool
*/
public function hasNextPage(): bool
{
@@ -324,7 +316,7 @@ public function nextPage()
/**
* Checks if the current page is the first page
*
- * @return boolean
+ * @return bool
*/
public function isFirstPage(): bool
{
@@ -334,7 +326,7 @@ public function isFirstPage(): bool
/**
* Checks if the current page is the last page
*
- * @return boolean
+ * @return bool
*/
public function isLastPage(): bool
{
@@ -397,6 +389,97 @@ public function rangeEnd(int $range = 5): int
return array_pop($range);
}
+ /**
+ * Sets the properties limit, total and page
+ * and validates that the properties match
+ *
+ * @param array $props Array with keys limit, total and/or page
+ * @return self
+ */
+ protected function setProperties(array $props)
+ {
+ $this->baseSetProperties($props);
+
+ // ensure that page is set to something, otherwise
+ // generate "default page" based on other params
+ if ($this->page === null) {
+ $this->page = $this->firstPage();
+ }
+
+ // allow a page value of 1 even if there are no pages;
+ // otherwise the exception will get thrown for this pretty common case
+ $min = $this->firstPage();
+ $max = $this->pages();
+ if ($this->page === 1 && $max === 0) {
+ $this->page = 0;
+ }
+
+ // validate page based on all params if validation is enabled,
+ // otherwise limit the page number to the bounds
+ if ($this->page < $min || $this->page > $max) {
+ if (static::$validate === true) {
+ throw new ErrorPageException('Pagination page ' . $this->page . ' does not exist, expected ' . $min . '-' . $max);
+ } else {
+ $this->page = max(min($this->page, $max), $min);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Sets the number of items per page
+ *
+ * @param int $limit
+ * @return self
+ */
+ protected function setLimit(int $limit = 20)
+ {
+ if ($limit < 1) {
+ throw new Exception('Invalid pagination limit: ' . $limit);
+ }
+
+ $this->limit = $limit;
+ return $this;
+ }
+
+ /**
+ * Sets the total number of items
+ *
+ * @param int $total
+ * @return self
+ */
+ protected function setTotal(int $total = 0)
+ {
+ if ($total < 0) {
+ throw new Exception('Invalid total number of items: ' . $total);
+ }
+
+ $this->total = $total;
+ return $this;
+ }
+
+ /**
+ * Sets the current page
+ *
+ * @param int|string|null $page Int or int in string form;
+ * automatically determined if null
+ * @return self
+ */
+ protected function setPage($page = null)
+ {
+ // if $page is null, it is set to a default in the setProperties() method
+ if ($page !== null) {
+ if (is_numeric($page) !== true || $page < 0) {
+ throw new Exception('Invalid page number: ' . $page);
+ }
+
+ $this->page = (int)$page;
+ }
+
+ return $this;
+ }
+
/**
* Returns an array with all properties
*
diff --git a/src/Toolkit/Query.php b/src/Toolkit/Query.php
index d608ad77be..391f0f26ae 100644
--- a/src/Toolkit/Query.php
+++ b/src/Toolkit/Query.php
@@ -114,7 +114,7 @@ protected function resolve(string $query)
/**
* Breaks the query string down into its components
*
- * @param string $query
+ * @param string $query
* @return array
*/
protected function parts(string $query): array
@@ -137,7 +137,7 @@ protected function parts(string $query): array
* Analyzes each part of the query string and
* extracts methods and method arguments.
*
- * @param string $part
+ * @param string $part
* @return array
*/
protected function part(string $part): array
@@ -158,7 +158,7 @@ protected function part(string $part): array
* Converts a parameter of query to
* proper type.
*
- * @param mixed $arg
+ * @param mixed $arg
* @return mixed
*/
protected function parameter($arg)
diff --git a/src/Toolkit/Str.php b/src/Toolkit/Str.php
index 1554e185ee..8ca6421f7d 100644
--- a/src/Toolkit/Str.php
+++ b/src/Toolkit/Str.php
@@ -169,9 +169,9 @@ public static function accepted(string $input): array
/**
* Returns the rest of the string after the given character
*
- * @param string $string
- * @param string $needle
- * @param bool $caseInsensitive
+ * @param string $string
+ * @param string $needle
+ * @param bool $caseInsensitive
* @return string
*/
public static function after(string $string, string $needle, bool $caseInsensitive = false): string
@@ -188,7 +188,7 @@ public static function after(string $string, string $needle, bool $caseInsensiti
/**
* Convert a string to 7-bit ASCII.
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function ascii(string $string): string
@@ -211,9 +211,9 @@ public static function ascii(string $string): string
/**
* Returns the beginning of a string before the given character
*
- * @param string $string
- * @param string $needle
- * @param bool $caseInsensitive
+ * @param string $string
+ * @param string $needle
+ * @param bool $caseInsensitive
* @return string
*/
public static function before(string $string, string $needle, bool $caseInsensitive = false): string
@@ -243,9 +243,9 @@ public static function between(string $string = null, string $start, string $end
/**
* Checks if a str contains another string
*
- * @param string $string
- * @param string $needle
- * @param bool $caseInsensitive
+ * @param string $string
+ * @param string $needle
+ * @param bool $caseInsensitive
* @return bool
*/
public static function contains(string $string = null, string $needle, bool $caseInsensitive = false): bool
@@ -279,7 +279,7 @@ public static function convert($string, $targetEncoding, $sourceEncoding = null)
/**
* Encode a string (used for email addresses)
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function encode(string $string): string
@@ -298,7 +298,7 @@ public static function encode(string $string): string
/**
* Tries to detect the string encoding
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function encoding(string $string): string
@@ -309,9 +309,9 @@ public static function encoding(string $string): string
/**
* Checks if a string ends with the passed needle
*
- * @param string $string
- * @param string $needle
- * @param bool $caseInsensitive
+ * @param string $string
+ * @param string $needle
+ * @param bool $caseInsensitive
* @return bool
*/
public static function endsWith(string $string, string $needle, bool $caseInsensitive = false): bool
@@ -335,11 +335,11 @@ public static function endsWith(string $string, string $needle, bool $caseInsens
* It removes all html tags first and then cuts the string
* according to the specified number of chars.
*
- * @param string $string The string to be shortened
- * @param int $chars The final number of characters the string should have
- * @param boolean $strip True: remove the HTML tags from the string first
- * @param string $rep The element, which should be added if the string is too long. Ellipsis is the default.
- * @return string The shortened string
+ * @param string $string The string to be shortened
+ * @param int $chars The final number of characters the string should have
+ * @param bool $strip True: remove the HTML tags from the string first
+ * @param string $rep The element, which should be added if the string is too long. Ellipsis is the default.
+ * @return string The shortened string
*/
public static function excerpt($string, $chars = 140, $strip = true, $rep = '…')
{
@@ -381,9 +381,9 @@ public static function float($value): string
/**
* Returns the rest of the string starting from the given character
*
- * @param string $string
- * @param string $needle
- * @param bool $caseInsensitive
+ * @param string $string
+ * @param string $needle
+ * @param bool $caseInsensitive
* @return string
*/
public static function from(string $string, string $needle, bool $caseInsensitive = false): string
@@ -401,7 +401,7 @@ public static function from(string $string, string $needle, bool $caseInsensitiv
* Checks if the given string is a URL
*
* @param string|null $string
- * @return boolean
+ * @return bool
*/
public static function isURL(string $string = null): bool
{
@@ -411,7 +411,7 @@ public static function isURL(string $string = null): bool
/**
* Convert a string to kebab case.
*
- * @param string $value
+ * @param string $value
* @return string
*/
public static function kebab(string $value = null): string
@@ -422,7 +422,7 @@ public static function kebab(string $value = null): string
/**
* A UTF-8 safe version of strlen()
*
- * @param string $string
+ * @param string $string
* @return int
*/
public static function length(string $string = null): int
@@ -433,7 +433,7 @@ public static function length(string $string = null): int
/**
* A UTF-8 safe version of strtolower()
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function lower(string $string = null): string
@@ -457,8 +457,8 @@ public static function ltrim(string $string, string $trim = ' '): string
/**
* Get a character pool with various possible combinations
*
- * @param string|array $type
- * @param boolean $array
+ * @param string|array $type
+ * @param bool $array
* @return string|array
*/
public static function pool($type, bool $array = true)
@@ -498,9 +498,9 @@ public static function pool($type, bool $array = true)
* Returns the position of a needle in a string
* if it can be found
*
- * @param string $string
- * @param string $needle
- * @param bool $caseInsensitive
+ * @param string $string
+ * @param string $needle
+ * @param bool $caseInsensitive
* @return int|bool
*/
public static function position(string $string = null, string $needle, bool $caseInsensitive = false)
@@ -565,15 +565,15 @@ public static function random(int $length = null, string $type = 'alphaNum')
* Replaces all or some occurrences of the search string with the replacement string
* Extension of the str_replace() function in PHP with an additional $limit parameter
*
- * @param string|array $string String being replaced on (haystack);
- * can be an array of multiple subject strings
- * @param string|array $search Value being searched for (needle)
- * @param string|array $replace Value to replace matches with
- * @param int|array $limit Maximum possible replacements for each search value;
- * multiple limits for each search value are supported;
- * defaults to no limit
- * @return string|array String with replaced values;
- * if $string is an array, array of strings
+ * @param string|array $string String being replaced on (haystack);
+ * can be an array of multiple subject strings
+ * @param string|array $search Value being searched for (needle)
+ * @param string|array $replace Value to replace matches with
+ * @param int|array $limit Maximum possible replacements for each search value;
+ * multiple limits for each search value are supported;
+ * defaults to no limit
+ * @return string|array String with replaced values;
+ * if $string is an array, array of strings
*/
public static function replace($string, $search, $replace, $limit = -1)
{
@@ -622,13 +622,13 @@ public static function replace($string, $search, $replace, $limit = -1)
* Generates a replacement array out of dynamic input data
* Used for Str::replace()
*
- * @param string|array $search Value being searched for (needle)
- * @param string|array $replace Value to replace matches with
- * @param int|array $limit Maximum possible replacements for each search value;
- * multiple limits for each search value are supported;
- * defaults to no limit
- * @return array List of replacement arrays, each with a
- * 'search', 'replace' and 'limit' attribute
+ * @param string|array $search Value being searched for (needle)
+ * @param string|array $replace Value to replace matches with
+ * @param int|array $limit Maximum possible replacements for each search value;
+ * multiple limits for each search value are supported;
+ * defaults to no limit
+ * @return array List of replacement arrays, each with a
+ * 'search', 'replace' and 'limit' attribute
*/
public static function replacements($search, $replace, $limit): array
{
@@ -673,9 +673,9 @@ public static function replacements($search, $replace, $limit): array
* Takes a replacement array and processes the replacements
* Used for Str::replace()
*
- * @param string $string String being replaced on (haystack)
- * @param array $replacements Replacement array from Str::replacements()
- * @return string String with replaced values
+ * @param string $string String being replaced on (haystack)
+ * @param array $replacements Replacement array from Str::replacements()
+ * @return string String with replaced values
*/
public static function replaceReplacements(string $string, array $replacements): string
{
@@ -736,12 +736,12 @@ public static function rtrim(string $string, string $trim = ' '): string
*
*
*
- * @param string $string The string to be shortened
- * @param int $length The final number of characters the
- * string should have
- * @param string $appendix The element, which should be added if the
- * string is too long. Ellipsis is the default.
- * @return string The shortened string
+ * @param string $string The string to be shortened
+ * @param int $length The final number of characters the
+ * string should have
+ * @param string $appendix The element, which should be added if the
+ * string is too long. Ellipsis is the default.
+ * @return string The shortened string
*/
public static function short(string $string = null, int $length = 0, string $appendix = '…'): ?string
{
@@ -759,13 +759,14 @@ public static function short(string $string = null, int $length = 0, string $app
/**
* Convert a string to a safe version to be used in a URL
*
- * @param string $string The unsafe string
- * @param string $separator To be used instead of space and
- * other non-word characters.
- * @param string $allowed List of all allowed characters (regex)
- * @return string The safe string
+ * @param string $string The unsafe string
+ * @param string $separator To be used instead of space and
+ * other non-word characters.
+ * @param string $allowed List of all allowed characters (regex)
+ * @param int $maxlength The maximum length of the slug
+ * @return string The safe string
*/
- public static function slug(string $string = null, string $separator = null, string $allowed = null): string
+ public static function slug(string $string = null, string $separator = null, string $allowed = null, int $maxlength = 128): string
{
$separator = $separator ?? static::$defaults['slug']['separator'];
$allowed = $allowed ?? static::$defaults['slug']['allowed'];
@@ -789,14 +790,15 @@ public static function slug(string $string = null, string $separator = null, str
$string = preg_replace('!^[^a-z0-9]+!', '', $string);
$string = preg_replace('![^a-z0-9]+$!', '', $string);
- return $string;
+ // cut the string after the given maxlength
+ return static::short($string, $maxlength, false);
}
/**
* Convert a string to snake case.
*
- * @param string $value
- * @param string $delimiter
+ * @param string $value
+ * @param string $delimiter
* @return string
*/
public static function snake(string $value = null, string $delimiter = '_'): string
@@ -814,10 +816,10 @@ public static function snake(string $value = null, string $delimiter = '_'): str
* and it has a built-in way to skip values
* which are too short.
*
- * @param string $string The string to split
- * @param string $separator The string to split by
- * @param int $length The min length of values.
- * @return array An array of found values
+ * @param string $string The string to split
+ * @param string $separator The string to split by
+ * @param int $length The min length of values.
+ * @return array An array of found values
*/
public static function split($string, string $separator = ',', int $length = 1): array
{
@@ -841,9 +843,9 @@ public static function split($string, string $separator = ',', int $length = 1):
/**
* Checks if a string starts with the passed needle
*
- * @param string $string
- * @param string $needle
- * @param bool $caseInsensitive
+ * @param string $string
+ * @param string $needle
+ * @param bool $caseInsensitive
* @return bool
*/
public static function startsWith(string $string = null, string $needle, bool $caseInsensitive = false): bool
@@ -858,9 +860,9 @@ public static function startsWith(string $string = null, string $needle, bool $c
/**
* A UTF-8 safe version of substr()
*
- * @param string $string
- * @param int $start
- * @param int $length
+ * @param string $string
+ * @param int $start
+ * @param int $length
* @return string
*/
public static function substr(string $string = null, int $start = 0, int $length = null): string
@@ -878,13 +880,13 @@ public static function substr(string $string = null, int $start = 0, int $length
*
*
*
- * @param string $string The string with placeholders
- * @param array $data Associative array with placeholders as
- * keys and replacements as values
- * @param string $fallback A fallback if a token does not have any matches
- * @param string $start Placeholder start characters
- * @param string $end Placeholder end characters
- * @return string The filled-in string
+ * @param string $string The string with placeholders
+ * @param array $data Associative array with placeholders as
+ * keys and replacements as values
+ * @param string $fallback A fallback if a token does not have any matches
+ * @param string $start Placeholder start characters
+ * @param string $end Placeholder end characters
+ * @return string The filled-in string
*/
public static function template(string $string = null, array $data = [], string $fallback = null, string $start = '{{', string $end = '}}'): string
{
@@ -969,7 +971,7 @@ public static function trim(string $string, string $trim = ' '): string
/**
* A UTF-8 safe version of ucfirst()
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function ucfirst(string $string = null): string
@@ -980,7 +982,7 @@ public static function ucfirst(string $string = null): string
/**
* A UTF-8 safe version of ucwords()
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function ucwords(string $string = null): string
@@ -998,8 +1000,8 @@ public static function ucwords(string $string = null): string
*
*
*
- * @param string $string
- * @return string The html string
+ * @param string $string
+ * @return string The html string
*/
public static function unhtml(string $string = null): string
{
@@ -1009,9 +1011,9 @@ public static function unhtml(string $string = null): string
/**
* Returns the beginning of a string until the given character
*
- * @param string $string
- * @param string $needle
- * @param bool $caseInsensitive
+ * @param string $string
+ * @param string $needle
+ * @param bool $caseInsensitive
* @return string
*/
public static function until(string $string, string $needle, bool $caseInsensitive = false): string
@@ -1028,7 +1030,7 @@ public static function until(string $string, string $needle, bool $caseInsensiti
/**
* A UTF-8 safe version of strotoupper()
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function upper(string $string = null): string
diff --git a/src/Toolkit/V.php b/src/Toolkit/V.php
index b5b6eed49c..37ba85317e 100644
--- a/src/Toolkit/V.php
+++ b/src/Toolkit/V.php
@@ -102,11 +102,11 @@ public static function validators(): array
* a set of rules, using all registered
* validators
*
- * @param mixed $value
- * @param array $rules
- * @param array $messages
- * @param boolean $fail
- * @return boolean|array
+ * @param mixed $value
+ * @param array $rules
+ * @param array $messages
+ * @param bool $fail
+ * @return bool|array
*/
public static function value($value, array $rules, array $messages = [], bool $fail = true)
{
@@ -142,9 +142,9 @@ public static function value($value, array $rules, array $messages = [], bool $f
* a set of rules, using all registered
* validators
*
- * @param array $input
- * @param array $rules
- * @return boolean
+ * @param array $input
+ * @param array $rules
+ * @return bool
*/
public static function input(array $input, array $rules): bool
{
@@ -179,9 +179,9 @@ public static function input(array $input, array $rules): bool
/**
* Calls an installed validator and passes all arguments
*
- * @param string $method
- * @param array $arguments
- * @return boolean
+ * @param string $method
+ * @param array $arguments
+ * @return bool
*/
public static function __callStatic(string $method, array $arguments): bool
{
@@ -481,7 +481,8 @@ public static function __callStatic(string $method, array $arguments): bool
*/
'url' => function ($value): bool {
// In search for the perfect regular expression: https://mathiasbynens.be/demo/url-regex
- $regex = '_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iu';
+ // Added localhost support and removed 127.*.*.* ip restriction
+ $regex = '_^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:localhost)|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$_iu';
return preg_match($regex, $value) !== 0;
}
];
diff --git a/src/Toolkit/View.php b/src/Toolkit/View.php
index a40559e0e1..db545918aa 100644
--- a/src/Toolkit/View.php
+++ b/src/Toolkit/View.php
@@ -34,7 +34,7 @@ class View
* Creates a new view object
*
* @param string $file
- * @param array $data
+ * @param array $data
*/
public function __construct(string $file, array $data = [])
{
@@ -56,7 +56,7 @@ public function data(): array
/**
* Checks if the template file exists
*
- * @return boolean
+ * @return bool
*/
public function exists(): bool
{
diff --git a/src/Toolkit/Xml.php b/src/Toolkit/Xml.php
index fdf000c933..563f57e8cb 100644
--- a/src/Toolkit/Xml.php
+++ b/src/Toolkit/Xml.php
@@ -56,11 +56,11 @@ class Xml
/**
* Creates an XML string from an array
*
- * @param string $props The source array
- * @param string $name The name of the root element
- * @param boolean $head Include the xml declaration head or not
- * @param int $level The indendation level
- * @return string The XML string
+ * @param string $props The source array
+ * @param string $name The name of the root element
+ * @param bool $head Include the xml declaration head or not
+ * @param int $level The indendation level
+ * @return string The XML string
*/
public static function create($props, string $name = 'root', bool $head = true, $level = 0): string
{
@@ -116,7 +116,7 @@ public static function create($props, string $name = 'root', bool $head = true,
*
*
*
- * @param string $string
+ * @param string $string
* @return string
*/
public static function decode(string $string = null): string
@@ -136,8 +136,8 @@ public static function decode(string $string = null): string
*
*
*
- * @param string $string
- * @param boolean $html True: convert to html first
+ * @param string $string
+ * @param bool $html True: convert to html first
* @return string
*/
public static function encode(string $string = null, bool $html = true): string
@@ -166,7 +166,7 @@ public static function entities(): array
/**
* Parses a XML string and returns an array
*
- * @param string $xml
+ * @param string $xml
* @return array|false
*/
public static function parse(string $xml = null)
diff --git a/tests/Cache/ApcuCacheTest.php b/tests/Cache/ApcuCacheTest.php
index 4d962939d0..14e50724bf 100755
--- a/tests/Cache/ApcuCacheTest.php
+++ b/tests/Cache/ApcuCacheTest.php
@@ -31,9 +31,9 @@ public function testOperations()
$this->assertTrue($cache->set('foo', 'A basic value', 10));
$this->assertTrue($cache->exists('foo'));
- $this->assertEquals('A basic value', $cache->retrieve('foo')->value());
- $this->assertEquals($time, $cache->created('foo'));
- $this->assertEquals($time + 600, $cache->expires('foo'));
+ $this->assertSame('A basic value', $cache->retrieve('foo')->value());
+ $this->assertSame($time, $cache->created('foo'));
+ $this->assertSame($time + 600, $cache->expires('foo'));
$this->assertTrue($cache->remove('foo'));
$this->assertFalse($cache->exists('foo'));
@@ -62,19 +62,19 @@ public function testOperationsWithPrefix()
$this->assertTrue($cache1->exists('foo'));
$this->assertFalse($cache2->exists('foo'));
- $this->assertEquals('A basic value', $cache1->retrieve('foo')->value());
- $this->assertEquals($time, $cache1->created('foo'));
- $this->assertEquals($time + 600, $cache1->expires('foo'));
+ $this->assertSame('A basic value', $cache1->retrieve('foo')->value());
+ $this->assertSame($time, $cache1->created('foo'));
+ $this->assertSame($time + 600, $cache1->expires('foo'));
$this->assertTrue($cache2->set('foo', 'Another basic value'));
$this->assertTrue($cache2->exists('foo'));
- $this->assertEquals('A basic value', $cache1->retrieve('foo')->value());
+ $this->assertSame('A basic value', $cache1->retrieve('foo')->value());
$this->assertTrue($cache1->remove('foo'));
$this->assertFalse($cache1->exists('foo'));
$this->assertNull($cache1->retrieve('foo'));
$this->assertTrue($cache2->exists('foo'));
- $this->assertEquals('Another basic value', $cache2->retrieve('foo')->value());
+ $this->assertSame('Another basic value', $cache2->retrieve('foo')->value());
}
/**
diff --git a/tests/Cache/CacheTest.php b/tests/Cache/CacheTest.php
index 8afdbb6623..279914f2b5 100755
--- a/tests/Cache/CacheTest.php
+++ b/tests/Cache/CacheTest.php
@@ -46,7 +46,7 @@ class CacheTest extends TestCase
public function testConstruct()
{
$cache = new TestCache(['some' => 'options']);
- $this->assertEquals(['some' => 'options'], $cache->options());
+ $this->assertSame(['some' => 'options'], $cache->options());
}
/**
@@ -58,12 +58,12 @@ public function testKey()
$method->setAccessible(true);
$cache = new TestCache();
- $this->assertEquals('foo', $method->invoke($cache, 'foo'));
+ $this->assertSame('foo', $method->invoke($cache, 'foo'));
$cache = new TestCache([
'prefix' => 'test'
]);
- $this->assertEquals('test/foo', $method->invoke($cache, 'foo'));
+ $this->assertSame('test/foo', $method->invoke($cache, 'foo'));
}
/**
@@ -74,25 +74,25 @@ public function testGet()
$cache = new TestCache();
$cache->set('foo', 'foo');
- $this->assertEquals('foo', $cache->get('foo'));
+ $this->assertSame('foo', $cache->get('foo'));
$cache->set('foo', ['this is' => 'an array']);
- $this->assertEquals(['this is' => 'an array'], $cache->get('foo'));
+ $this->assertSame(['this is' => 'an array'], $cache->get('foo'));
$cache->set('foo', 1234);
- $this->assertEquals(1234, $cache->get('foo'));
+ $this->assertSame(1234, $cache->get('foo'));
$cache->set('foo', null);
- $this->assertEquals(null, $cache->get('foo', 'default'));
+ $this->assertSame(null, $cache->get('foo', 'default'));
- $this->assertEquals('default', $cache->get('doesnotexist', 'default'));
+ $this->assertSame('default', $cache->get('doesnotexist', 'default'));
$cache->set('notyetexpired', 'foo', 60, time());
- $this->assertEquals('foo', $cache->get('notyetexpired'));
+ $this->assertSame('foo', $cache->get('notyetexpired'));
$cache->set('expired', 'foo', 60, 0);
$this->assertTrue(isset($cache->store['expired']));
- $this->assertEquals('default', $cache->get('expired', 'default'));
+ $this->assertSame('default', $cache->get('expired', 'default'));
$this->assertFalse(isset($cache->store['expired']));
}
@@ -105,9 +105,9 @@ public function testExpiration()
$method->setAccessible(true);
$cache = new TestCache();
- $this->assertEquals(0, $method->invoke($cache));
- $this->assertEquals(0, $method->invoke($cache, 0));
- $this->assertEquals(time() + 600, $method->invoke($cache, 10));
+ $this->assertSame(0, $method->invoke($cache));
+ $this->assertSame(0, $method->invoke($cache, 0));
+ $this->assertSame(time() + 600, $method->invoke($cache, 10));
}
/**
@@ -118,10 +118,10 @@ public function testExpires()
$cache = new TestCache();
$cache->set('foo', 'foo', 12);
- $this->assertEquals(time() + 720, $cache->expires('foo'));
+ $this->assertSame(time() + 720, $cache->expires('foo'));
$cache->set('foo', 'foo');
- $this->assertEquals(null, $cache->expires('foo'));
+ $this->assertSame(null, $cache->expires('foo'));
$this->assertFalse($cache->expires('doesnotexist'));
}
@@ -154,8 +154,8 @@ public function testCreated()
$cache = new TestCache();
$cache->set('foo', 'foo', 60, 1234);
- $this->assertEquals(1234, $cache->created('foo'));
- $this->assertEquals(1234, $cache->modified('foo'));
+ $this->assertSame(1234, $cache->created('foo'));
+ $this->assertSame(1234, $cache->modified('foo'));
$this->assertFalse($cache->created('doesnotexist'));
$this->assertFalse($cache->modified('doesnotexist'));
diff --git a/tests/Cache/FileCacheTest.php b/tests/Cache/FileCacheTest.php
index 702f94c72c..8d05d7a2b5 100755
--- a/tests/Cache/FileCacheTest.php
+++ b/tests/Cache/FileCacheTest.php
@@ -52,26 +52,26 @@ public function testFile()
$cache = new FileCache([
'root' => $root = __DIR__ . '/fixtures/file'
]);
- $this->assertEquals($root . '/test', $method->invoke($cache, 'test'));
+ $this->assertSame($root . '/test', $method->invoke($cache, 'test'));
$cache = new FileCache([
'root' => $root = __DIR__ . '/fixtures/file',
'extension' => 'cache'
]);
- $this->assertEquals($root . '/test.cache', $method->invoke($cache, 'test'));
+ $this->assertSame($root . '/test.cache', $method->invoke($cache, 'test'));
$cache = new FileCache([
'root' => $root = __DIR__ . '/fixtures/file',
'prefix' => 'test1'
]);
- $this->assertEquals($root . '/test1/test', $method->invoke($cache, 'test'));
+ $this->assertSame($root . '/test1/test', $method->invoke($cache, 'test'));
$cache = new FileCache([
'root' => $root = __DIR__ . '/fixtures/file',
'prefix' => 'test1',
'extension' => 'cache'
]);
- $this->assertEquals($root . '/test1/test.cache', $method->invoke($cache, 'test'));
+ $this->assertSame($root . '/test1/test.cache', $method->invoke($cache, 'test'));
}
/**
@@ -91,9 +91,9 @@ public function testOperations()
$this->assertFileExists($root . '/foo');
$this->assertTrue($cache->exists('foo'));
- $this->assertEquals('A basic value', $cache->retrieve('foo')->value());
- $this->assertEquals($time, $cache->created('foo'));
- $this->assertEquals($time + 600, $cache->expires('foo'));
+ $this->assertSame('A basic value', $cache->retrieve('foo')->value());
+ $this->assertSame($time, $cache->created('foo'));
+ $this->assertSame($time + 600, $cache->expires('foo'));
$this->assertTrue($cache->remove('foo'));
$this->assertFileNotExists($root . '/foo');
@@ -121,9 +121,9 @@ public function testOperationsWithExtension()
$this->assertFileExists($root . '/foo.cache');
$this->assertTrue($cache->exists('foo'));
- $this->assertEquals('A basic value', $cache->retrieve('foo')->value());
- $this->assertEquals($time, $cache->created('foo'));
- $this->assertEquals($time + 600, $cache->expires('foo'));
+ $this->assertSame('A basic value', $cache->retrieve('foo')->value());
+ $this->assertSame($time, $cache->created('foo'));
+ $this->assertSame($time + 600, $cache->expires('foo'));
$this->assertTrue($cache->remove('foo'));
$this->assertFileNotExists($root . '/foo.cache');
@@ -154,20 +154,20 @@ public function testOperationsWithPrefix()
$this->assertFileExists($root . '/test1/foo');
$this->assertTrue($cache1->exists('foo'));
$this->assertFalse($cache2->exists('foo'));
- $this->assertEquals('A basic value', $cache1->retrieve('foo')->value());
- $this->assertEquals($time, $cache1->created('foo'));
- $this->assertEquals($time + 600, $cache1->expires('foo'));
+ $this->assertSame('A basic value', $cache1->retrieve('foo')->value());
+ $this->assertSame($time, $cache1->created('foo'));
+ $this->assertSame($time + 600, $cache1->expires('foo'));
$this->assertTrue($cache2->set('foo', 'Another basic value'));
$this->assertTrue($cache2->exists('foo'));
- $this->assertEquals('A basic value', $cache1->retrieve('foo')->value());
+ $this->assertSame('A basic value', $cache1->retrieve('foo')->value());
$this->assertTrue($cache1->remove('foo'));
$this->assertFileNotExists($root . '/test1/foo');
$this->assertFalse($cache1->exists('foo'));
$this->assertNull($cache1->retrieve('foo'));
$this->assertTrue($cache2->exists('foo'));
- $this->assertEquals('Another basic value', $cache2->retrieve('foo')->value());
+ $this->assertSame('Another basic value', $cache2->retrieve('foo')->value());
}
/**
diff --git a/tests/Cache/MemCachedTest.php b/tests/Cache/MemCachedTest.php
index aeaa4824c6..5bc7a6b6f6 100755
--- a/tests/Cache/MemCachedTest.php
+++ b/tests/Cache/MemCachedTest.php
@@ -43,9 +43,9 @@ public function testOperations()
$this->assertTrue($cache->set('foo', 'A basic value', 10));
$this->assertTrue($cache->exists('foo'));
- $this->assertEquals('A basic value', $cache->retrieve('foo')->value());
- $this->assertEquals($time, $cache->created('foo'));
- $this->assertEquals($time + 600, $cache->expires('foo'));
+ $this->assertSame('A basic value', $cache->retrieve('foo')->value());
+ $this->assertSame($time, $cache->created('foo'));
+ $this->assertSame($time + 600, $cache->expires('foo'));
$this->assertTrue($cache->remove('foo'));
$this->assertFalse($cache->exists('foo'));
@@ -73,19 +73,19 @@ public function testOperationsWithPrefix()
$this->assertTrue($cache1->exists('foo'));
$this->assertFalse($cache2->exists('foo'));
- $this->assertEquals('A basic value', $cache1->retrieve('foo')->value());
- $this->assertEquals($time, $cache1->created('foo'));
- $this->assertEquals($time + 600, $cache1->expires('foo'));
+ $this->assertSame('A basic value', $cache1->retrieve('foo')->value());
+ $this->assertSame($time, $cache1->created('foo'));
+ $this->assertSame($time + 600, $cache1->expires('foo'));
$this->assertTrue($cache2->set('foo', 'Another basic value'));
$this->assertTrue($cache2->exists('foo'));
- $this->assertEquals('A basic value', $cache1->retrieve('foo')->value());
+ $this->assertSame('A basic value', $cache1->retrieve('foo')->value());
$this->assertTrue($cache1->remove('foo'));
$this->assertFalse($cache1->exists('foo'));
$this->assertNull($cache1->retrieve('foo'));
$this->assertTrue($cache2->exists('foo'));
- $this->assertEquals('Another basic value', $cache2->retrieve('foo')->value());
+ $this->assertSame('Another basic value', $cache2->retrieve('foo')->value());
}
/**
diff --git a/tests/Cache/MemoryCacheTest.php b/tests/Cache/MemoryCacheTest.php
index 09cd8ae665..21d63e760a 100755
--- a/tests/Cache/MemoryCacheTest.php
+++ b/tests/Cache/MemoryCacheTest.php
@@ -22,9 +22,9 @@ public function testOperations()
$this->assertTrue($cache->set('foo', 'A basic value', 10));
$this->assertTrue($cache->exists('foo'));
- $this->assertEquals('A basic value', $cache->retrieve('foo')->value());
- $this->assertEquals($time, $cache->created('foo'));
- $this->assertEquals($time + 600, $cache->expires('foo'));
+ $this->assertSame('A basic value', $cache->retrieve('foo')->value());
+ $this->assertSame($time, $cache->created('foo'));
+ $this->assertSame($time + 600, $cache->expires('foo'));
$this->assertTrue($cache->remove('foo'));
$this->assertFalse($cache->exists('foo'));
@@ -48,19 +48,19 @@ public function testOperationsWithMultipleInstances()
$this->assertTrue($cache1->exists('foo'));
$this->assertFalse($cache2->exists('foo'));
- $this->assertEquals('A basic value', $cache1->retrieve('foo')->value());
- $this->assertEquals($time, $cache1->created('foo'));
- $this->assertEquals($time + 600, $cache1->expires('foo'));
+ $this->assertSame('A basic value', $cache1->retrieve('foo')->value());
+ $this->assertSame($time, $cache1->created('foo'));
+ $this->assertSame($time + 600, $cache1->expires('foo'));
$this->assertTrue($cache2->set('foo', 'Another basic value'));
$this->assertTrue($cache2->exists('foo'));
- $this->assertEquals('A basic value', $cache1->retrieve('foo')->value());
+ $this->assertSame('A basic value', $cache1->retrieve('foo')->value());
$this->assertTrue($cache1->remove('foo'));
$this->assertFalse($cache1->exists('foo'));
$this->assertNull($cache1->retrieve('foo'));
$this->assertTrue($cache2->exists('foo'));
- $this->assertEquals('Another basic value', $cache2->retrieve('foo')->value());
+ $this->assertSame('Another basic value', $cache2->retrieve('foo')->value());
}
/**
diff --git a/tests/Cache/ValueTest.php b/tests/Cache/ValueTest.php
index 44a18a0998..ffcf37892a 100755
--- a/tests/Cache/ValueTest.php
+++ b/tests/Cache/ValueTest.php
@@ -16,10 +16,10 @@ class ValueTest extends TestCase
public function testCreated()
{
$value = new Value('foo');
- $this->assertEquals(time(), $value->created());
+ $this->assertSame(time(), $value->created());
$value = new Value('foo', 0, 1000);
- $this->assertEquals(1000, $value->created());
+ $this->assertSame(1000, $value->created());
}
/**
@@ -34,10 +34,10 @@ public function testExpires()
$this->assertNull($value->expires());
$value = new Value('foo', 1000, 0);
- $this->assertEquals(1000 * 60, $value->expires());
+ $this->assertSame(1000 * 60, $value->expires());
$value = new Value('foo', 1000, 10000);
- $this->assertEquals(10000 + 1000 * 60, $value->expires());
+ $this->assertSame(10000 + 1000 * 60, $value->expires());
}
/**
@@ -52,10 +52,10 @@ public function testArrayConversion()
'value' => 'foo'
];
$value = Value::fromArray($data);
- $this->assertEquals(10000, $value->created());
+ $this->assertSame(10000, $value->created());
$this->assertNull($value->expires());
- $this->assertEquals('foo', $value->value());
- $this->assertEquals($data, $value->toArray());
+ $this->assertSame('foo', $value->value());
+ $this->assertSame($data, $value->toArray());
$time = time();
$data = [
@@ -64,10 +64,10 @@ public function testArrayConversion()
'value' => ['this is' => 'an array']
];
$value = Value::fromArray($data);
- $this->assertEquals($time, $value->created());
- $this->assertEquals($time + 1000 * 60, $value->expires());
- $this->assertEquals(['this is' => 'an array'], $value->value());
- $this->assertEquals([
+ $this->assertSame($time, $value->created());
+ $this->assertSame($time + 1000 * 60, $value->expires());
+ $this->assertSame(['this is' => 'an array'], $value->value());
+ $this->assertSame([
'created' => $time,
'minutes' => 1000,
'value' => ['this is' => 'an array']
@@ -79,10 +79,10 @@ public function testArrayConversion()
'value' => 'foo'
];
$value = Value::fromArray($data);
- $this->assertEquals(10000, $value->created());
+ $this->assertSame(10000, $value->created());
$this->assertNull($value->expires());
- $this->assertEquals('foo', $value->value());
- $this->assertEquals([
+ $this->assertSame('foo', $value->value());
+ $this->assertSame([
'created' => 10000,
'minutes' => 0,
'value' => 'foo'
@@ -116,10 +116,10 @@ public function testJsonConversion()
'value' => 'foo'
]);
$value = Value::fromJson($data);
- $this->assertEquals(10000, $value->created());
+ $this->assertSame(10000, $value->created());
$this->assertNull($value->expires());
- $this->assertEquals('foo', $value->value());
- $this->assertEquals($data, $value->toJson());
+ $this->assertSame('foo', $value->value());
+ $this->assertSame($data, $value->toJson());
$time = time();
$data = json_encode([
@@ -128,10 +128,10 @@ public function testJsonConversion()
'value' => ['this is' => 'an array']
]);
$value = Value::fromJson($data);
- $this->assertEquals($time, $value->created());
- $this->assertEquals($time + 1000 * 60, $value->expires());
- $this->assertEquals(['this is' => 'an array'], $value->value());
- $this->assertEquals(json_encode([
+ $this->assertSame($time, $value->created());
+ $this->assertSame($time + 1000 * 60, $value->expires());
+ $this->assertSame(['this is' => 'an array'], $value->value());
+ $this->assertSame(json_encode([
'created' => $time,
'minutes' => 1000,
'value' => ['this is' => 'an array']
@@ -143,10 +143,10 @@ public function testJsonConversion()
'value' => 'foo'
]);
$value = Value::fromJson($data);
- $this->assertEquals(10000, $value->created());
+ $this->assertSame(10000, $value->created());
$this->assertNull($value->expires());
- $this->assertEquals('foo', $value->value());
- $this->assertEquals(json_encode([
+ $this->assertSame('foo', $value->value());
+ $this->assertSame(json_encode([
'created' => 10000,
'minutes' => 0,
'value' => 'foo'
@@ -168,12 +168,12 @@ public function testJsonConversion()
public function testValue()
{
$value = new Value('foo');
- $this->assertEquals('foo', $value->value());
+ $this->assertSame('foo', $value->value());
$value = new Value(['this is' => 'an array']);
- $this->assertEquals(['this is' => 'an array'], $value->value());
+ $this->assertSame(['this is' => 'an array'], $value->value());
$value = new Value(12345);
- $this->assertEquals(12345, $value->value());
+ $this->assertSame(12345, $value->value());
}
}
diff --git a/tests/Cms/Api/ApiTest.php b/tests/Cms/Api/ApiTest.php
index 688e12d740..ace8ec80ce 100644
--- a/tests/Cms/Api/ApiTest.php
+++ b/tests/Cms/Api/ApiTest.php
@@ -6,6 +6,11 @@
class ApiTest extends TestCase
{
+ protected $api;
+ protected $locale;
+ protected $app;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
@@ -42,18 +47,113 @@ public function setUp(): void
'api' => [
'authentication' => function () {
return true;
- }
- ]
+ },
+ 'routes' => [
+ [
+ 'pattern' => 'foo',
+ 'method' => 'GET',
+ 'action' => function () {
+ return 'something';
+ }
+ ]
+ ]
+ ],
+ 'locale' => 'de_DE.UTF-8'
],
]);
$this->app->impersonate('kirby');
$this->api = $this->app->api();
+
+ $this->locale = setlocale(LC_ALL, 0);
}
public function tearDown(): void
{
Dir::remove($this->fixtures);
+ setlocale(LC_ALL, $this->locale);
+ }
+
+ public function testCallLocaleSingleLang1()
+ {
+ setlocale(LC_ALL, 'C');
+ $this->assertSame('C', setlocale(LC_ALL, 0));
+
+ $this->assertSame('something', $this->api->call('foo'));
+ $this->assertSame('de_DE.UTF-8', setlocale(LC_ALL, 0));
+ }
+
+ public function testCallLocaleSingleLang2()
+ {
+ setlocale(LC_ALL, 'C');
+ $this->assertSame('C', setlocale(LC_ALL, 0));
+
+ $_GET['language'] = 'en';
+
+ $this->assertSame('something', $this->api->call('foo'));
+ $this->assertSame('de_DE.UTF-8', setlocale(LC_ALL, 0));
+
+ $_GET = [];
+ }
+
+ public function testCallLocaleMultiLang1()
+ {
+ setlocale(LC_ALL, 'C');
+ $this->assertSame('C', setlocale(LC_ALL, 0));
+
+ $this->app = $this->app->clone([
+ 'languages' => [
+ [
+ 'code' => 'en',
+ 'name' => 'English',
+ 'default' => true,
+ 'locale' => 'en_US.UTF-8',
+ 'url' => '/',
+ ],
+ [
+ 'code' => 'de',
+ 'name' => 'Deutsch',
+ 'locale' => 'de_AT.UTF-8',
+ 'url' => '/de',
+ ],
+ ]
+ ]);
+ $this->api = $this->app->api();
+
+ $this->assertSame('something', $this->api->call('foo'));
+ $this->assertSame('en_US.UTF-8', setlocale(LC_ALL, 0));
+ }
+
+ public function testCallLocaleMultiLang2()
+ {
+ setlocale(LC_ALL, 'C');
+ $this->assertSame('C', setlocale(LC_ALL, 0));
+
+ $this->app = $this->app->clone([
+ 'languages' => [
+ [
+ 'code' => 'en',
+ 'name' => 'English',
+ 'default' => true,
+ 'locale' => 'en_US.UTF-8',
+ 'url' => '/',
+ ],
+ [
+ 'code' => 'de',
+ 'name' => 'Deutsch',
+ 'locale' => 'de_AT.UTF-8',
+ 'url' => '/de',
+ ],
+ ]
+ ]);
+ $this->api = $this->app->api();
+
+ $_GET['language'] = 'de';
+
+ $this->assertSame('something', $this->api->call('foo'));
+ $this->assertSame('de_AT.UTF-8', setlocale(LC_ALL, 0));
+
+ $_GET = [];
}
public function testLanguage()
diff --git a/tests/Cms/Api/collections/ChildrenApiCollectionTest.php b/tests/Cms/Api/collections/ChildrenApiCollectionTest.php
index 4fda8cf7fc..fee467cb7f 100644
--- a/tests/Cms/Api/collections/ChildrenApiCollectionTest.php
+++ b/tests/Cms/Api/collections/ChildrenApiCollectionTest.php
@@ -4,6 +4,9 @@
class ChildrenApiCollectionTest extends TestCase
{
+ protected $api;
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/collections/FilesApiCollectionTest.php b/tests/Cms/Api/collections/FilesApiCollectionTest.php
index 02b110d666..153cf31d2e 100644
--- a/tests/Cms/Api/collections/FilesApiCollectionTest.php
+++ b/tests/Cms/Api/collections/FilesApiCollectionTest.php
@@ -4,6 +4,9 @@
class FilesApiCollectionTest extends TestCase
{
+ protected $api;
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/collections/LanguagesApiCollectionTest.php b/tests/Cms/Api/collections/LanguagesApiCollectionTest.php
index fd5bce8519..22713252f9 100644
--- a/tests/Cms/Api/collections/LanguagesApiCollectionTest.php
+++ b/tests/Cms/Api/collections/LanguagesApiCollectionTest.php
@@ -4,6 +4,9 @@
class LanguagesApiCollectionTest extends TestCase
{
+ protected $api;
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/collections/PagesApiCollectionTest.php b/tests/Cms/Api/collections/PagesApiCollectionTest.php
index 468a5fe6ca..a273b1b02b 100644
--- a/tests/Cms/Api/collections/PagesApiCollectionTest.php
+++ b/tests/Cms/Api/collections/PagesApiCollectionTest.php
@@ -4,6 +4,9 @@
class PagesApiCollectionTest extends TestCase
{
+ protected $api;
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/collections/RolesApiCollectionTest.php b/tests/Cms/Api/collections/RolesApiCollectionTest.php
index 322355ac45..0d45d2f060 100644
--- a/tests/Cms/Api/collections/RolesApiCollectionTest.php
+++ b/tests/Cms/Api/collections/RolesApiCollectionTest.php
@@ -4,6 +4,9 @@
class RolesApiCollectionTest extends TestCase
{
+ protected $api;
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/collections/TranslationsApiCollectionTest.php b/tests/Cms/Api/collections/TranslationsApiCollectionTest.php
index 34694e4fb1..602ebbf493 100644
--- a/tests/Cms/Api/collections/TranslationsApiCollectionTest.php
+++ b/tests/Cms/Api/collections/TranslationsApiCollectionTest.php
@@ -4,6 +4,9 @@
class TranslationsApiCollectionTest extends TestCase
{
+ protected $api;
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/collections/UsersApiCollectionTest.php b/tests/Cms/Api/collections/UsersApiCollectionTest.php
index d4cbb7d9d4..8ad28af73f 100644
--- a/tests/Cms/Api/collections/UsersApiCollectionTest.php
+++ b/tests/Cms/Api/collections/UsersApiCollectionTest.php
@@ -4,6 +4,9 @@
class UsersApiCollectionTest extends TestCase
{
+ protected $api;
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/models/FileBlueprintApiModelTest.php b/tests/Cms/Api/models/FileBlueprintApiModelTest.php
index 2004657177..3a07480f33 100644
--- a/tests/Cms/Api/models/FileBlueprintApiModelTest.php
+++ b/tests/Cms/Api/models/FileBlueprintApiModelTest.php
@@ -4,6 +4,10 @@
class FileBlueprintApiModelTest extends TestCase
{
+ protected $api;
+ protected $app;
+ protected $file;
+
public function attr($object, $attr)
{
return $this->api->resolve($object)->select($attr)->toArray()[$attr];
diff --git a/tests/Cms/Api/models/PageApiModelTest.php b/tests/Cms/Api/models/PageApiModelTest.php
index a3ad62e60d..c9515fc47c 100644
--- a/tests/Cms/Api/models/PageApiModelTest.php
+++ b/tests/Cms/Api/models/PageApiModelTest.php
@@ -4,6 +4,9 @@
class PageApiModelTest extends TestCase
{
+ protected $api;
+ protected $app;
+
public function attr($object, $attr)
{
return $this->api->resolve($object)->select($attr)->toArray()[$attr];
diff --git a/tests/Cms/Api/models/PageBlueprintApiModelTest.php b/tests/Cms/Api/models/PageBlueprintApiModelTest.php
index 7fd90aca8c..ee15e0f6a0 100644
--- a/tests/Cms/Api/models/PageBlueprintApiModelTest.php
+++ b/tests/Cms/Api/models/PageBlueprintApiModelTest.php
@@ -4,6 +4,9 @@
class PageBlueprintApiModelTest extends TestCase
{
+ protected $api;
+ protected $app;
+
public function attr($object, $attr)
{
return $this->api->resolve($object)->select($attr)->toArray()[$attr];
diff --git a/tests/Cms/Api/models/SiteApiModelTest.php b/tests/Cms/Api/models/SiteApiModelTest.php
index 12bf818ad7..ae3a2d152e 100644
--- a/tests/Cms/Api/models/SiteApiModelTest.php
+++ b/tests/Cms/Api/models/SiteApiModelTest.php
@@ -4,6 +4,9 @@
class SiteApiModelTest extends TestCase
{
+ protected $api;
+ protected $app;
+
public function attr($object, $attr)
{
return $this->api->resolve($object)->select($attr)->toArray()[$attr];
diff --git a/tests/Cms/Api/models/UserBlueprintApiModelTest.php b/tests/Cms/Api/models/UserBlueprintApiModelTest.php
index 3acab880bd..83c246f7f6 100644
--- a/tests/Cms/Api/models/UserBlueprintApiModelTest.php
+++ b/tests/Cms/Api/models/UserBlueprintApiModelTest.php
@@ -4,6 +4,10 @@
class UserBlueprintApiModelTest extends TestCase
{
+ protected $api;
+ protected $app;
+ protected $user;
+
public function attr($object, $attr)
{
return $this->api->resolve($object)->select($attr)->toArray()[$attr];
diff --git a/tests/Cms/Api/routes/AuthRoutesTest.php b/tests/Cms/Api/routes/AuthRoutesTest.php
index 19b8c5058e..26504e8e50 100644
--- a/tests/Cms/Api/routes/AuthRoutesTest.php
+++ b/tests/Cms/Api/routes/AuthRoutesTest.php
@@ -6,6 +6,8 @@
class AuthRoutesTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/routes/LanguagesRoutesTest.php b/tests/Cms/Api/routes/LanguagesRoutesTest.php
index 537229ab01..8c164209fb 100644
--- a/tests/Cms/Api/routes/LanguagesRoutesTest.php
+++ b/tests/Cms/Api/routes/LanguagesRoutesTest.php
@@ -6,6 +6,8 @@
class LanguagesRoutesTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/routes/PagesRoutesTest.php b/tests/Cms/Api/routes/PagesRoutesTest.php
index dc25d0c3c2..fb0393e021 100644
--- a/tests/Cms/Api/routes/PagesRoutesTest.php
+++ b/tests/Cms/Api/routes/PagesRoutesTest.php
@@ -79,6 +79,9 @@ public function testFiles()
[
'slug' => 'a',
'files' => [
+ [
+ 'filename' => 'c.jpg',
+ ],
[
'filename' => 'a.jpg',
],
@@ -95,8 +98,10 @@ public function testFiles()
$response = $app->api()->call('pages/a/files');
- $this->assertEquals('a.jpg', $response['data'][0]['filename']);
- $this->assertEquals('b.jpg', $response['data'][1]['filename']);
+ $this->assertCount(3, $response['data']);
+ $this->assertSame('a.jpg', $response['data'][0]['filename']);
+ $this->assertSame('b.jpg', $response['data'][1]['filename']);
+ $this->assertSame('c.jpg', $response['data'][2]['filename']);
}
public function testFilesSorted()
diff --git a/tests/Cms/Api/routes/RolesRoutesTest.php b/tests/Cms/Api/routes/RolesRoutesTest.php
index 096e4d6744..0ebd868e5a 100644
--- a/tests/Cms/Api/routes/RolesRoutesTest.php
+++ b/tests/Cms/Api/routes/RolesRoutesTest.php
@@ -6,6 +6,8 @@
class RolesRoutesTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/routes/SiteRoutesTest.php b/tests/Cms/Api/routes/SiteRoutesTest.php
index 802d6e0b0c..ca2ec8b367 100644
--- a/tests/Cms/Api/routes/SiteRoutesTest.php
+++ b/tests/Cms/Api/routes/SiteRoutesTest.php
@@ -6,6 +6,8 @@
class SiteRoutesTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
@@ -58,6 +60,9 @@ public function testFiles()
$app = $this->app->clone([
'site' => [
'files' => [
+ [
+ 'filename' => 'c.jpg',
+ ],
[
'filename' => 'a.jpg',
],
@@ -72,8 +77,10 @@ public function testFiles()
$response = $app->api()->call('site/files');
- $this->assertEquals('a.jpg', $response['data'][0]['filename']);
- $this->assertEquals('b.jpg', $response['data'][1]['filename']);
+ $this->assertCount(3, $response['data']);
+ $this->assertSame('a.jpg', $response['data'][0]['filename']);
+ $this->assertSame('b.jpg', $response['data'][1]['filename']);
+ $this->assertSame('c.jpg', $response['data'][2]['filename']);
}
public function testFilesSorted()
diff --git a/tests/Cms/Api/routes/SystemRoutesTest.php b/tests/Cms/Api/routes/SystemRoutesTest.php
index 7e20adc8fd..d394405da3 100644
--- a/tests/Cms/Api/routes/SystemRoutesTest.php
+++ b/tests/Cms/Api/routes/SystemRoutesTest.php
@@ -7,6 +7,8 @@
class SystemRoutesTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/routes/TranslationsRoutesTest.php b/tests/Cms/Api/routes/TranslationsRoutesTest.php
index 6e789e07f1..27c05f5009 100644
--- a/tests/Cms/Api/routes/TranslationsRoutesTest.php
+++ b/tests/Cms/Api/routes/TranslationsRoutesTest.php
@@ -6,6 +6,8 @@
class TranslationsRoutesTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Api/routes/UsersRoutesTest.php b/tests/Cms/Api/routes/UsersRoutesTest.php
index e149b6ab4c..b4ba0cffed 100644
--- a/tests/Cms/Api/routes/UsersRoutesTest.php
+++ b/tests/Cms/Api/routes/UsersRoutesTest.php
@@ -6,6 +6,8 @@
class UsersRoutesTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
@@ -14,9 +16,11 @@ public function setUp(): void
],
'users' => [
[
+ 'name' => 'Bastian',
'email' => 'admin@getkirby.com',
],
[
+ 'name' => 'Sonja',
'email' => 'editor@getkirby.com',
]
]
@@ -71,6 +75,20 @@ public function testSearchWithPostRequest()
$this->assertCount(1, $response['data']);
$this->assertEquals('editor@getkirby.com', $response['data'][0]['email']);
}
+
+ public function testSearchName()
+ {
+ $app = $this->app;
+
+ $response = $app->api()->call('users/search', 'GET', [
+ 'query' => [
+ 'q' => 'Bastian'
+ ]
+ ]);
+
+ $this->assertCount(1, $response['data']);
+ $this->assertEquals('admin@getkirby.com', $response['data'][0]['email']);
+ }
public function testFiles()
{
@@ -79,6 +97,9 @@ public function testFiles()
[
'email' => 'test@getkirby.com',
'files' => [
+ [
+ 'filename' => 'c.jpg',
+ ],
[
'filename' => 'a.jpg',
],
@@ -94,8 +115,10 @@ public function testFiles()
$response = $app->api()->call('users/test@getkirby.com/files');
- $this->assertEquals('a.jpg', $response['data'][0]['filename']);
- $this->assertEquals('b.jpg', $response['data'][1]['filename']);
+ $this->assertCount(3, $response['data']);
+ $this->assertSame('a.jpg', $response['data'][0]['filename']);
+ $this->assertSame('b.jpg', $response['data'][1]['filename']);
+ $this->assertSame('c.jpg', $response['data'][2]['filename']);
}
public function testFilesSorted()
diff --git a/tests/Cms/App/AppComponentsTest.php b/tests/Cms/App/AppComponentsTest.php
index 86e5a49217..dee0c134c6 100644
--- a/tests/Cms/App/AppComponentsTest.php
+++ b/tests/Cms/App/AppComponentsTest.php
@@ -7,6 +7,8 @@
class AppComponentsTest extends TestCase
{
+ protected $kirby;
+
public function setUp(): void
{
$this->kirby = new App([
@@ -16,6 +18,19 @@ public function setUp(): void
]);
}
+ public function testDump()
+ {
+ $kirby = $this->kirby->clone([
+ 'components' => [
+ 'dump' => function ($kirby, $variable) {
+ return $variable;
+ }
+ ]
+ ]);
+
+ $this->assertEquals('test', dump('test'));
+ }
+
public function testMarkdown()
{
$text = 'Test';
@@ -46,6 +61,88 @@ public function testSmartypants()
$this->assertEquals($expected, $this->kirby->smartypants($text));
}
+ public function testSmartypantsDisabled()
+ {
+ $this->kirby = $this->kirby->clone([
+ 'options' => [
+ 'smartypants' => false
+ ]
+ ]);
+
+ $text = '"Test"';
+ $expected = '"Test"';
+
+ $this->assertSame($expected, $this->kirby->smartypants($text));
+ }
+
+ public function testSmartypantsMultiLang()
+ {
+ $this->kirby = $this->kirby->clone([
+ 'options' => [
+ 'languages' => true,
+ 'smartypants' => true
+ ],
+ 'languages' => [
+ [
+ 'code' => 'en',
+ 'name' => 'English',
+ 'default' => true,
+ 'locale' => 'en_US',
+ 'url' => '/',
+ 'smartypants' => [
+ 'doublequote.open' => '<',
+ 'doublequote.close' => '>'
+ ]
+ ],
+ [
+ 'code' => 'de',
+ 'name' => 'Deutsch',
+ 'locale' => 'de_DE',
+ 'url' => '/de',
+ 'smartypants' => [
+ 'doublequote.open' => '<<',
+ 'doublequote.close' => '>>'
+ ]
+ ]
+ ]
+ ]);
+
+ $text = '"Test"';
+ $expected = '';
+
+ $this->assertSame($expected, $this->kirby->smartypants($text));
+ }
+
+ public function testSmartypantsDefaultOptionsOnMultiLang()
+ {
+ $this->kirby = $this->kirby->clone([
+ 'options' => [
+ 'languages' => true,
+ 'smartypants' => true
+ ],
+ 'languages' => [
+ [
+ 'code' => 'en',
+ 'name' => 'English',
+ 'default' => true,
+ 'locale' => 'en_US',
+ 'url' => '/'
+ ],
+ [
+ 'code' => 'de',
+ 'name' => 'Deutsch',
+ 'locale' => 'de_DE',
+ 'url' => '/de'
+ ]
+ ]
+ ]);
+
+ $text = '"Test"';
+ $expected = '“Test”';
+
+ $this->assertSame($expected, $this->kirby->smartypants($text));
+ }
+
public function testSmartypantsCachedInstance()
{
$text = '"Test"';
diff --git a/tests/Cms/App/AppIoTest.php b/tests/Cms/App/AppIoTest.php
index b72ea02e8c..01b07d90d2 100644
--- a/tests/Cms/App/AppIoTest.php
+++ b/tests/Cms/App/AppIoTest.php
@@ -2,7 +2,7 @@
namespace Kirby\Cms;
-use Exception;
+use Kirby\Exception\Exception;
use Kirby\Http\Response;
use PHPUnit\Framework\TestCase;
@@ -12,22 +12,45 @@ public function app()
{
return new App([
'roots' => [
- 'index' => '/dev/null'
+ 'index' => '/dev/null',
+ 'templates' => __DIR__ . '/fixtures/AppIoTest/templates'
]
]);
}
public function testException()
{
- $response = $this->app()->io(new Exception('Nope'));
+ $response = $this->app()->io(new Exception([
+ 'fallback' => 'Nope',
+ 'httpCode' => 501
+ ]));
- $this->assertEquals(500, $response->code());
+ $this->assertEquals(501, $response->code());
$this->assertEquals('Nope', $response->body());
}
+ public function testExceptionErrorPage()
+ {
+ $app = $this->app()->clone([
+ 'site' => [
+ 'children' => [
+ [
+ 'slug' => 'error',
+ 'template' => 'error'
+ ]
+ ]
+ ]
+ ]);
+
+ $response = $app->io(new Exception('Nope'));
+
+ $this->assertEquals(500, $response->code());
+ $this->assertEquals('Error: Nope', $response->body());
+ }
+
public function testExceptionWithInvalidHttpCode()
{
- $response = $this->app()->io(new Exception('Nope', 8000));
+ $response = $this->app()->io(new \Exception('Nope', 8000));
$this->assertEquals(500, $response->code());
$this->assertEquals('Nope', $response->body());
@@ -64,6 +87,56 @@ public function testResponse()
$this->assertEquals($input, $response);
}
+ public function testPage()
+ {
+ $input = new Page([
+ 'slug' => 'test',
+ 'template' => 'test'
+ ]);
+
+ $response = $this->app()->io($input);
+
+ $this->assertEquals(200, $response->code());
+ $this->assertEquals('Test template', $response->body());
+ }
+
+ public function testPageErrorPageException()
+ {
+ $input = new Page([
+ 'slug' => 'test',
+ 'template' => 'errorpage-exception'
+ ]);
+
+ $response = $this->app()->io($input);
+
+ $this->assertEquals(403, $response->code());
+ $this->assertEquals('Exception message', $response->body());
+ }
+
+ public function testPageErrorPageExceptionErrorPage()
+ {
+ $app = $this->app()->clone([
+ 'site' => [
+ 'children' => [
+ [
+ 'slug' => 'error',
+ 'template' => 'error'
+ ]
+ ]
+ ]
+ ]);
+
+ $input = new Page([
+ 'slug' => 'test',
+ 'template' => 'errorpage-exception'
+ ]);
+
+ $response = $app->io($input);
+
+ $this->assertEquals(403, $response->code());
+ $this->assertEquals('Error: Exception message', $response->body());
+ }
+
public function testString()
{
$response = $this->app()->io('Test');
diff --git a/tests/Cms/App/AppPluginsTest.php b/tests/Cms/App/AppPluginsTest.php
index b4ac34c74b..e856d144c4 100644
--- a/tests/Cms/App/AppPluginsTest.php
+++ b/tests/Cms/App/AppPluginsTest.php
@@ -26,6 +26,11 @@ class DummyUser extends User
class AppPluginsTest extends TestCase
{
+ public $fixtures;
+
+ // used for testPluginLoader()
+ public static $calledPluginsLoadedHook = false;
+
public function setUp(): void
{
App::destroy();
@@ -138,7 +143,7 @@ public function testApiRouteCallbackPlugins()
return [
[
'pattern' => 'b',
- 'action' => function () use ($kirby) {
+ 'action' => function () {
return 'b';
}
]
@@ -355,7 +360,7 @@ public function testHook()
'index' => '/dev/null'
],
'hooks' => [
- 'testHook' => function ($message) use ($phpUnit, &$executed) {
+ 'testHook' => function ($message) use ($phpUnit) {
$phpUnit->assertEquals('test', $message);
}
]
@@ -823,4 +828,56 @@ public function testUsersMethod()
// reset methods
Users::$methods = [];
}
+
+ public function testPluginLoader()
+ {
+ $phpUnit = $this;
+ $executed = 0;
+
+ $kirby = new App([
+ 'roots' => [
+ 'index' => $this->fixtures = __DIR__ . '/fixtures/AppPluginsTest',
+ 'plugins' => $this->fixtures . '/site/plugins-loader'
+ ],
+ 'hooks' => [
+ 'system.loadPlugins:after' => function () use ($phpUnit, &$executed) {
+ if (count($this->plugins()) === 2) {
+ $phpUnit->assertEquals([
+ 'kirby/manual1' => new Plugin('kirby/manual1', []),
+ 'kirby/manual2' => new Plugin('kirby/manual2', [])
+ ], $this->plugins());
+ } else {
+ $phpUnit->assertEquals([
+ 'kirby/test1' => new Plugin('kirby/test1', [
+ 'hooks' => [
+ 'system.loadPlugins:after' => function () {
+ // just a dummy closure to compare against
+ }
+ ],
+ 'root' => $phpUnit->fixtures . '/site/plugins-loader/test1'
+ ])
+ ], $this->plugins());
+ }
+
+ $executed++;
+ }
+ ]
+ ]);
+
+ // the hook defined inside the test1 plugin should also have been called
+ $this->assertTrue(static::$calledPluginsLoadedHook);
+
+ // try loading again (which should *not* trigger the hooks again)
+ $kirby->plugins();
+
+ // overwrite plugins with a custom array
+ $expected = [
+ 'kirby/manual1' => new Plugin('kirby/manual1', []),
+ 'kirby/manual2' => new Plugin('kirby/manual2', [])
+ ];
+ $this->assertEquals($expected, $kirby->plugins($expected));
+
+ // hook should have been called only once after the firs initialization
+ $this->assertEquals(1, $executed);
+ }
}
diff --git a/tests/Cms/App/AppResolveTest.php b/tests/Cms/App/AppResolveTest.php
index 4129a7c3d1..00f646eca9 100644
--- a/tests/Cms/App/AppResolveTest.php
+++ b/tests/Cms/App/AppResolveTest.php
@@ -6,6 +6,8 @@
class AppResolveTest extends TestCase
{
+ protected $fixtures;
+
public function setUp(): void
{
$this->fixtures = __DIR__ . '/fixtures/AppResolveTest';
diff --git a/tests/Cms/App/AppTest.php b/tests/Cms/App/AppTest.php
index 6eb6c1e091..08dc21779e 100644
--- a/tests/Cms/App/AppTest.php
+++ b/tests/Cms/App/AppTest.php
@@ -10,6 +10,8 @@
*/
class AppTest extends TestCase
{
+ protected $fixtures;
+
public function setUp(): void
{
$this->fixtures = __DIR__ . '/fixtures/AppTest';
@@ -208,6 +210,26 @@ public function testOptions()
$this->assertEquals($options, $app->options());
}
+ public function testOptionsOnReady()
+ {
+ App::destroy();
+
+ $app = new App([
+ 'roots' => [
+ 'index' => '/dev/null'
+ ],
+ 'options' => [
+ 'ready' => function ($kirby) {
+ return [
+ 'test' => $kirby->root('index')
+ ];
+ }
+ ]
+ ]);
+
+ $this->assertEquals('/dev/null', $app->option('test'));
+ }
+
public function testRolesFromFixtures()
{
$app = new App([
diff --git a/tests/Cms/App/AppTranslationsTest.php b/tests/Cms/App/AppTranslationsTest.php
index 8865de4230..d2c73ba9f8 100644
--- a/tests/Cms/App/AppTranslationsTest.php
+++ b/tests/Cms/App/AppTranslationsTest.php
@@ -8,6 +8,9 @@
class AppTranslationsTest extends TestCase
{
+ protected $app;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/App/AppUsersTest.php b/tests/Cms/App/AppUsersTest.php
index a200ef3dd8..34cdca9f73 100644
--- a/tests/Cms/App/AppUsersTest.php
+++ b/tests/Cms/App/AppUsersTest.php
@@ -7,6 +7,9 @@
class AppUsersTest extends TestCase
{
+ protected $app;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/App/fixtures/AppIoTest/templates/error.php b/tests/Cms/App/fixtures/AppIoTest/templates/error.php
new file mode 100644
index 0000000000..36e326d6c9
--- /dev/null
+++ b/tests/Cms/App/fixtures/AppIoTest/templates/error.php
@@ -0,0 +1 @@
+Error: = $errorMessage ?>
\ No newline at end of file
diff --git a/tests/Cms/App/fixtures/AppIoTest/templates/errorpage-exception.php b/tests/Cms/App/fixtures/AppIoTest/templates/errorpage-exception.php
new file mode 100644
index 0000000000..54d2f25af6
--- /dev/null
+++ b/tests/Cms/App/fixtures/AppIoTest/templates/errorpage-exception.php
@@ -0,0 +1,6 @@
+ 'Exception message',
+ 'httpCode' => 403
+]);
diff --git a/tests/Cms/App/fixtures/AppIoTest/templates/test.php b/tests/Cms/App/fixtures/AppIoTest/templates/test.php
new file mode 100644
index 0000000000..518887dfd5
--- /dev/null
+++ b/tests/Cms/App/fixtures/AppIoTest/templates/test.php
@@ -0,0 +1 @@
+Test template
\ No newline at end of file
diff --git a/tests/Cms/App/fixtures/AppPluginsTest/site/plugins-loader/.test4/index.php b/tests/Cms/App/fixtures/AppPluginsTest/site/plugins-loader/.test4/index.php
new file mode 100644
index 0000000000..4a5579a24c
--- /dev/null
+++ b/tests/Cms/App/fixtures/AppPluginsTest/site/plugins-loader/.test4/index.php
@@ -0,0 +1,3 @@
+ [
+ 'system.loadPlugins:after' => function () {
+ AppPluginsTest::$calledPluginsLoadedHook = true;
+ }
+ ]
+]);
diff --git a/tests/Cms/App/fixtures/AppPluginsTest/site/plugins-loader/test5.php b/tests/Cms/App/fixtures/AppPluginsTest/site/plugins-loader/test5.php
new file mode 100644
index 0000000000..db0c980f4d
--- /dev/null
+++ b/tests/Cms/App/fixtures/AppPluginsTest/site/plugins-loader/test5.php
@@ -0,0 +1,3 @@
+app = new App([
diff --git a/tests/Cms/Auth/AuthCsrfTest.php b/tests/Cms/Auth/AuthCsrfTest.php
index 22552a530f..373d952e69 100644
--- a/tests/Cms/Auth/AuthCsrfTest.php
+++ b/tests/Cms/Auth/AuthCsrfTest.php
@@ -7,6 +7,10 @@
*/
class AuthCsrfTest extends TestCase
{
+ protected $app;
+ protected $auth;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Auth/AuthProtectionTest.php b/tests/Cms/Auth/AuthProtectionTest.php
index f0c00af439..f2821e9bcf 100644
--- a/tests/Cms/Auth/AuthProtectionTest.php
+++ b/tests/Cms/Auth/AuthProtectionTest.php
@@ -9,6 +9,10 @@
*/
class AuthProtectionTest extends TestCase
{
+ protected $app;
+ protected $auth;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Auth/AuthTest.php b/tests/Cms/Auth/AuthTest.php
index 937fe4f859..1b355e1bd1 100644
--- a/tests/Cms/Auth/AuthTest.php
+++ b/tests/Cms/Auth/AuthTest.php
@@ -10,6 +10,10 @@
*/
class AuthTest extends TestCase
{
+ protected $app;
+ protected $auth;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Blueprints/BlueprintExtendAndUnsetTest.php b/tests/Cms/Blueprints/BlueprintExtendAndUnsetTest.php
index ee536c73c3..e9dcfe5a7f 100644
--- a/tests/Cms/Blueprints/BlueprintExtendAndUnsetTest.php
+++ b/tests/Cms/Blueprints/BlueprintExtendAndUnsetTest.php
@@ -6,6 +6,8 @@
class BlueprintExtendAndUnset extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Blueprints/BlueprintFieldTest.php b/tests/Cms/Blueprints/BlueprintFieldTest.php
index cefe78c5e5..841f288205 100644
--- a/tests/Cms/Blueprints/BlueprintFieldTest.php
+++ b/tests/Cms/Blueprints/BlueprintFieldTest.php
@@ -6,6 +6,8 @@
class BlueprintFieldTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Blueprints/BlueprintFieldsTest.php b/tests/Cms/Blueprints/BlueprintFieldsTest.php
index f6795fc1a9..f39cecb98b 100644
--- a/tests/Cms/Blueprints/BlueprintFieldsTest.php
+++ b/tests/Cms/Blueprints/BlueprintFieldsTest.php
@@ -6,6 +6,8 @@
class BlueprintFieldsTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Blueprints/BlueprintPresetsTest.php b/tests/Cms/Blueprints/BlueprintPresetsTest.php
index fff584de03..8244612254 100644
--- a/tests/Cms/Blueprints/BlueprintPresetsTest.php
+++ b/tests/Cms/Blueprints/BlueprintPresetsTest.php
@@ -4,6 +4,8 @@
class BlueprintPresetsTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Blueprints/BlueprintTest.php b/tests/Cms/Blueprints/BlueprintTest.php
index 2d2d297608..95ee76a1af 100644
--- a/tests/Cms/Blueprints/BlueprintTest.php
+++ b/tests/Cms/Blueprints/BlueprintTest.php
@@ -6,6 +6,8 @@
class BlueprintTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
@@ -234,7 +236,7 @@ public function testNestedFields()
$this->assertArrayHasKey('test', $blueprint->fields());
$this->assertArrayNotHasKey('child-field', $blueprint->fields());
}
-
+
public function testInvalidSectionType()
{
$blueprint = new Blueprint([
@@ -252,17 +254,41 @@ public function testInvalidSectionType()
]
]
]);
-
+
try {
$sections = $blueprint->tab('main')['columns'][0]['sections'];
} catch (\Exception $e) {
$this->assertNull($e->getMessage(), 'Failed to get sections.');
}
-
+
$this->assertEquals(true, is_array($sections));
$this->assertEquals(1, sizeof($sections));
$this->assertEquals(true, array_key_exists('main', $sections));
$this->assertEquals(true, array_key_exists('headline', $sections['main']));
$this->assertEquals('Invalid section type for section "main"', $sections['main']['headline']);
}
+
+ public function testSectionTypeFromName()
+ {
+ // with options
+ $blueprint = new Blueprint([
+ 'model' => 'test',
+ 'sections' => [
+ 'info' => [
+ ]
+ ]
+ ]);
+
+ $this->assertEquals('info', $blueprint->sections()['info']->type());
+
+ // by just passing true
+ $blueprint = new Blueprint([
+ 'model' => 'test',
+ 'sections' => [
+ 'info' => true
+ ]
+ ]);
+
+ $this->assertEquals('info', $blueprint->sections()['info']->type());
+ }
}
diff --git a/tests/Cms/Collections/CollectionTest.php b/tests/Cms/Collections/CollectionTest.php
index 3e116eda8d..0194af3f77 100644
--- a/tests/Cms/Collections/CollectionTest.php
+++ b/tests/Cms/Collections/CollectionTest.php
@@ -7,6 +7,9 @@
class MockObject extends Model
{
+ protected $id;
+ protected $group;
+
public function __construct(array $props = [])
{
$this->id = $props['id'];
diff --git a/tests/Cms/Collections/CollectionTestCase.php b/tests/Cms/Collections/CollectionTestCase.php
index 64ed249326..0dc7113a56 100644
--- a/tests/Cms/Collections/CollectionTestCase.php
+++ b/tests/Cms/Collections/CollectionTestCase.php
@@ -38,17 +38,17 @@ public function collectionPagination()
public function assertCollectionCount(int $count)
{
- return $this->assertCount($count, $this->collection());
+ $this->assertCount($count, $this->collection());
}
public function assertCollectionHasPagination()
{
- return $this->assertInstanceOf(Pagination::class, $this->collectionPagination());
+ $this->assertInstanceOf(Pagination::class, $this->collectionPagination());
}
public function assertCollectionHasNoPagination()
{
- return $this->assertNotInstanceOf(Pagination::class, $this->collectionPagination());
+ $this->assertNotInstanceOf(Pagination::class, $this->collectionPagination());
}
public function testCollectionType()
diff --git a/tests/Cms/Collections/SearchTest.php b/tests/Cms/Collections/SearchTest.php
index a594deb7c3..e97b1b4055 100644
--- a/tests/Cms/Collections/SearchTest.php
+++ b/tests/Cms/Collections/SearchTest.php
@@ -2,8 +2,6 @@
namespace Kirby\Cms;
-use Kirby\Toolkit\Collection;
-
class SearchTest extends TestCase
{
public function testCollection()
diff --git a/tests/Cms/Content/ContentTest.php b/tests/Cms/Content/ContentTest.php
index ec0d4be900..b6edc1f856 100644
--- a/tests/Cms/Content/ContentTest.php
+++ b/tests/Cms/Content/ContentTest.php
@@ -135,7 +135,7 @@ public function testSetParent()
public function testToArray()
{
- return $this->assertEquals($this->mockData(), $this->mockObject()->toArray());
+ $this->assertEquals($this->mockData(), $this->mockObject()->toArray());
}
public function testUpdate()
@@ -150,6 +150,6 @@ public function testUpdate()
public function testDebuginfo()
{
- return $this->assertEquals($this->mockData(), $this->mockObject()->__debugInfo());
+ $this->assertEquals($this->mockData(), $this->mockObject()->__debugInfo());
}
}
diff --git a/tests/Cms/Emails/EmailTest.php b/tests/Cms/Emails/EmailTest.php
index 027a8483e2..c234751fdf 100644
--- a/tests/Cms/Emails/EmailTest.php
+++ b/tests/Cms/Emails/EmailTest.php
@@ -159,6 +159,7 @@ public function testEmailWithCollectionObject()
/**
* @runInSeparateProcess
+ * @preserveGlobalState disabled
*/
public function testEmailUserData()
{
diff --git a/tests/Cms/Facades/DirTest.php b/tests/Cms/Facades/DirTest.php
index a7a4d04ce7..9b077a9461 100644
--- a/tests/Cms/Facades/DirTest.php
+++ b/tests/Cms/Facades/DirTest.php
@@ -8,6 +8,8 @@
class DirTest extends TestCase
{
+ protected $fixtures;
+
public function setUp(): void
{
Dir::remove($this->fixtures = __DIR__ . '/fixtures/DirTest');
diff --git a/tests/Cms/Facades/RTest.php b/tests/Cms/Facades/RTest.php
index 5c28e82fc2..13344b938e 100644
--- a/tests/Cms/Facades/RTest.php
+++ b/tests/Cms/Facades/RTest.php
@@ -4,6 +4,8 @@
class RTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Facades/STest.php b/tests/Cms/Facades/STest.php
index 4f6eda82cc..0f03833eb7 100644
--- a/tests/Cms/Facades/STest.php
+++ b/tests/Cms/Facades/STest.php
@@ -4,6 +4,9 @@
class STest extends TestCase
{
+ protected $app;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Facades/UrlTest.php b/tests/Cms/Facades/UrlTest.php
index 514c1e8ab3..11f4e8cf3e 100644
--- a/tests/Cms/Facades/UrlTest.php
+++ b/tests/Cms/Facades/UrlTest.php
@@ -7,6 +7,8 @@
class UrlTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Facades/VTest.php b/tests/Cms/Facades/VTest.php
index 48dd82b618..c278461cd0 100644
--- a/tests/Cms/Facades/VTest.php
+++ b/tests/Cms/Facades/VTest.php
@@ -6,6 +6,8 @@
class VTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Facades/VisitorTest.php b/tests/Cms/Facades/VisitorTest.php
index 3c19ef702e..710a2df63e 100644
--- a/tests/Cms/Facades/VisitorTest.php
+++ b/tests/Cms/Facades/VisitorTest.php
@@ -4,6 +4,8 @@
class VisitorTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Fields/FieldMethodsTest.php b/tests/Cms/Fields/FieldMethodsTest.php
index e0b7379514..29c6bd28d1 100644
--- a/tests/Cms/Fields/FieldMethodsTest.php
+++ b/tests/Cms/Fields/FieldMethodsTest.php
@@ -483,6 +483,14 @@ public function testHtml()
$this->assertEquals('ö', $this->field('ö')->html());
}
+ public function testNl2br()
+ {
+ $input = 'Multiline' . PHP_EOL . 'test' . PHP_EOL . 'string';
+ $expected = 'Multiline
' . PHP_EOL . 'test
' . PHP_EOL . 'string';
+
+ $this->assertEquals($expected, $this->field($input)->nl2br()->value());
+ }
+
public function testKirbytext()
{
$kirbytext = '(link: # text: Test)';
@@ -509,6 +517,14 @@ public function testKirbytags()
$this->assertEquals($expected, $this->field($kirbytext)->kirbytags());
}
+ public function testInline()
+ {
+ $html = 'Headline
Subtitle with link.
';
+ $expected = 'Headline Subtitle with link.';
+
+ $this->assertEquals($expected, $this->field($html)->inline());
+ }
+
public function testLower()
{
$this->assertEquals('abc', $this->field('ABC')->lower());
diff --git a/tests/Cms/Files/FileActionsTest.php b/tests/Cms/Files/FileActionsTest.php
index ca91ad30a8..54670777f6 100644
--- a/tests/Cms/Files/FileActionsTest.php
+++ b/tests/Cms/Files/FileActionsTest.php
@@ -252,10 +252,10 @@ public function testCreateHooks($parent)
$app = $this->app->clone([
'hooks' => [
- 'file.create:before' => function (File $file, Image $image) use (&$before, $phpunit, $parent) {
+ 'file.create:before' => function (File $file, Image $image) use (&$before) {
$before = true;
},
- 'file.create:after' => function (File $file) use (&$after, $phpunit, $parent) {
+ 'file.create:after' => function (File $file) use (&$after, $phpunit) {
$phpunit->assertTrue($file->siblings(true)->has($file));
$phpunit->assertTrue($file->parent()->files()->has($file));
$phpunit->assertEquals('test.md', $file->filename());
diff --git a/tests/Cms/Files/FileModificationsTest.php b/tests/Cms/Files/FileModificationsTest.php
index 15e685206f..b7120de11d 100644
--- a/tests/Cms/Files/FileModificationsTest.php
+++ b/tests/Cms/Files/FileModificationsTest.php
@@ -6,6 +6,8 @@
class FileModificationsTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Files/FilePickerTest.php b/tests/Cms/Files/FilePickerTest.php
new file mode 100644
index 0000000000..71ad5c7561
--- /dev/null
+++ b/tests/Cms/Files/FilePickerTest.php
@@ -0,0 +1,44 @@
+app = new App([
+ 'roots' => [
+ 'index' => '/dev/null'
+ ],
+ 'site' => [
+ 'files' => [
+ ['filename' => 'a.jpg'],
+ ['filename' => 'b.jpg'],
+ ['filename' => 'c.jpg']
+ ]
+ ]
+ ]);
+
+ $this->app->impersonate('kirby');
+ }
+
+ public function testDefaults()
+ {
+ $picker = new FilePicker();
+
+ $this->assertCount(3, $picker->items());
+ }
+
+ public function testQuery()
+ {
+ $picker = new FilePicker([
+ 'query' => 'site.files.offset(1)'
+ ]);
+
+ $this->assertCount(2, $picker->items());
+ }
+}
diff --git a/tests/Cms/Files/FileRulesTest.php b/tests/Cms/Files/FileRulesTest.php
index c323597891..becbc2810c 100644
--- a/tests/Cms/Files/FileRulesTest.php
+++ b/tests/Cms/Files/FileRulesTest.php
@@ -4,6 +4,8 @@
class FileRulesTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Files/FileTest.php b/tests/Cms/Files/FileTest.php
index 2c9714c90a..b5ea7a8558 100644
--- a/tests/Cms/Files/FileTest.php
+++ b/tests/Cms/Files/FileTest.php
@@ -9,6 +9,14 @@ class FileTestModel extends File
{
}
+class FileTestForceLocked extends File
+{
+ public function isLocked(): bool
+ {
+ return true;
+ }
+}
+
class FileTest extends TestCase
{
protected function defaults(): array
@@ -170,7 +178,7 @@ public function testParentId()
public function testDefaultPage()
{
- return $this->assertNull($this->file()->page());
+ $this->assertNull($this->file()->page());
}
public function testUrl()
@@ -274,6 +282,56 @@ public function testPanelIconWithRatio()
$this->assertEquals($expected, $icon);
}
+ public function testPanelOptions()
+ {
+ $file = new File([
+ 'filename' => 'test.jpg',
+ ]);
+
+ $file->kirby()->impersonate('kirby');
+
+ $expected = [
+ 'changeName' => true,
+ 'create' => true,
+ 'delete' => true,
+ 'replace' => true,
+ 'update' => true,
+ ];
+
+ $this->assertEquals($expected, $file->panelOptions());
+ }
+
+ public function testPanelOptionsWithLockedFile()
+ {
+ $file = new FileTestForceLocked([
+ 'filename' => 'test.jpg',
+ ]);
+
+ $file->kirby()->impersonate('kirby');
+
+ // without override
+ $expected = [
+ 'changeName' => false,
+ 'create' => false,
+ 'delete' => false,
+ 'replace' => false,
+ 'update' => false,
+ ];
+
+ $this->assertEquals($expected, $file->panelOptions());
+
+ // with override
+ $expected = [
+ 'changeName' => false,
+ 'create' => false,
+ 'delete' => true,
+ 'replace' => false,
+ 'update' => false,
+ ];
+
+ $this->assertEquals($expected, $file->panelOptions(['delete']));
+ }
+
public function testPanelUrl()
{
$app = new App([
diff --git a/tests/Cms/Files/FileVersionTest.php b/tests/Cms/Files/FileVersionTest.php
index 312b7c9aa3..cc3869c155 100644
--- a/tests/Cms/Files/FileVersionTest.php
+++ b/tests/Cms/Files/FileVersionTest.php
@@ -4,6 +4,8 @@
class FileVersionTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Files/HasFilesTest.php b/tests/Cms/Files/HasFilesTest.php
index 50b76d14c1..b127c599be 100644
--- a/tests/Cms/Files/HasFilesTest.php
+++ b/tests/Cms/Files/HasFilesTest.php
@@ -22,6 +22,8 @@ public function files()
class HasFilesTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Helpers/HelpersTest.php b/tests/Cms/Helpers/HelpersTest.php
index d2002cd355..824818d4b0 100644
--- a/tests/Cms/Helpers/HelpersTest.php
+++ b/tests/Cms/Helpers/HelpersTest.php
@@ -10,6 +10,7 @@
class HelpersTest extends TestCase
{
+ protected $fixtures;
protected $kirby;
public function setUp(): void
@@ -154,6 +155,23 @@ public function testCssHelperWithArray()
$this->assertEquals($expected, $result);
}
+ public function testDeprecated()
+ {
+ // with disabled debug mode
+ $this->assertFalse(deprecated('The xyz method is deprecated.'));
+
+ $this->kirby = $this->kirby->clone([
+ 'options' => [
+ 'debug' => true
+ ]
+ ]);
+
+ // with enabled debug mode
+ $this->expectException('Whoops\Exception\ErrorException');
+ $this->expectExceptionMessage('The xyz method is deprecated.');
+ deprecated('The xyz method is deprecated.');
+ }
+
public function testDumpHelperOnCli()
{
$this->assertEquals("test\n", dump('test', false));
@@ -639,6 +657,15 @@ public function testSvgWithMissingFile()
$this->assertFalse(svg('somefile.svg'));
}
+ public function testSvgWithFileObject()
+ {
+ $file = $this->createMock(File::class);
+ $file->method('__call')->willReturn('test');
+ $file->method('extension')->willReturn('svg');
+
+ $this->assertEquals('test', svg($file));
+ }
+
public function testTwitter()
{
// simple
@@ -693,14 +720,48 @@ public function testVideo()
$this->assertEquals($expected, $video);
}
+ public function testYoutubeVideoWithOptions()
+ {
+ $video = video('https://www.youtube.com/watch?v=xB3s_f7PzYk', [
+ 'youtube' => [
+ 'controls' => 0
+ ]
+ ]);
+
+ $expected = '';
+
+ $this->assertEquals($expected, $video);
+ }
+
+ public function testVimeoVideoWithOptions()
+ {
+ $video = video('https://vimeo.com/335292911', [
+ 'vimeo' => [
+ 'controls' => 0
+ ]
+ ]);
+
+ $expected = '';
+
+ $this->assertEquals($expected, $video);
+ }
+
public function testVimeo()
{
- $video = video('https://vimeo.com/335292911');
+ $video = vimeo('https://vimeo.com/335292911');
$expected = '';
$this->assertEquals($expected, $video);
}
+ public function testVimeoWithOptions()
+ {
+ $video = vimeo('https://vimeo.com/335292911', ['controls' => 0]);
+ $expected = '';
+
+ $this->assertEquals($expected, $video);
+ }
+
public function testWidont()
{
$result = widont('This is a headline');
@@ -716,4 +777,12 @@ public function testYoutube()
$this->assertEquals($expected, $video);
}
+
+ public function testYoutubeWithOptions()
+ {
+ $video = youtube('https://www.youtube.com/watch?v=xB3s_f7PzYk', ['controls' => 0]);
+ $expected = '';
+
+ $this->assertEquals($expected, $video);
+ }
}
diff --git a/tests/Cms/Ingredients/IngredientsTest.php b/tests/Cms/Ingredients/IngredientsTest.php
index a6b3848e23..3313c2d881 100644
--- a/tests/Cms/Ingredients/IngredientsTest.php
+++ b/tests/Cms/Ingredients/IngredientsTest.php
@@ -6,6 +6,8 @@
class IngredientsTest extends TestCase
{
+ protected $ingredients;
+
public function setUp(): void
{
$this->ingredients = Ingredients::bake([
diff --git a/tests/Cms/Languages/LanguageRouterTest.php b/tests/Cms/Languages/LanguageRouterTest.php
index 4ccf6f528b..e14791b4a5 100644
--- a/tests/Cms/Languages/LanguageRouterTest.php
+++ b/tests/Cms/Languages/LanguageRouterTest.php
@@ -6,6 +6,8 @@
class LanguageRouterTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
App::destroy();
diff --git a/tests/Cms/Languages/LanguageTest.php b/tests/Cms/Languages/LanguageTest.php
index e4c0d0e1b2..2a26293b7f 100644
--- a/tests/Cms/Languages/LanguageTest.php
+++ b/tests/Cms/Languages/LanguageTest.php
@@ -338,4 +338,97 @@ public function testRoot()
$this->assertEquals($fixtures . '/site/languages/de.php', $language->root());
}
+
+ public function pathProvider()
+ {
+ return [
+ [null, 'en'],
+ ['/', ''],
+ ['/en', 'en'],
+ ['/en/', 'en'],
+ ['https://getkirby.com/en', 'en'],
+ ['https://getkirby.com/en/', 'en'],
+ ['https://getkirby.com/sub/sub', 'sub/sub'],
+ ['https://getkirby.com/sub/sub/', 'sub/sub'],
+ ];
+ }
+
+ /**
+ * @dataProvider pathProvider
+ */
+ public function testPath($input, $expected)
+ {
+ $language = new Language([
+ 'code' => 'en',
+ 'url' => $input
+ ]);
+
+ $this->assertEquals($expected, $language->path());
+ }
+
+ public function patternProvider()
+ {
+ return [
+ [null, 'en/(:all?)'],
+ ['/', '(:all)'],
+ ['/en', 'en/(:all?)'],
+ ['/en/', 'en/(:all?)'],
+ ['https://getkirby.com', '(:all)'],
+ ['https://getkirby.com/', '(:all)'],
+ ['https://getkirby.com/en', 'en/(:all?)'],
+ ['https://getkirby.com/en/', 'en/(:all?)'],
+ ['https://getkirby.com/sub/sub', 'sub/sub/(:all?)'],
+ ['https://getkirby.com/sub/sub/', 'sub/sub/(:all?)'],
+ ];
+ }
+
+ /**
+ * @dataProvider patternProvider
+ */
+ public function testPattern($input, $expected)
+ {
+ $language = new Language([
+ 'code' => 'en',
+ 'url' => $input
+ ]);
+
+ $this->assertEquals($expected, $language->pattern());
+ }
+
+ public function baseUrlProvider()
+ {
+ return [
+ ['https://getkirby.com', null, 'https://getkirby.com'],
+ ['https://getkirby.com', '/en', 'https://getkirby.com'],
+ ['https://getkirby.com', 'https://getkirby.de', 'https://getkirby.de'],
+ ['https://getkirby.com', 'https://getkirby.de/en', 'https://getkirby.de'],
+ ['http://localhost/example.com', null, 'http://localhost/example.com'],
+ ['http://localhost/example.com', '/en', 'http://localhost/example.com'],
+ ['http://localhost/example.com', 'http://getkirby.com', 'http://getkirby.com'],
+ ['http://localhost/example.com', 'http://getkirby.com/en', 'http://getkirby.com'],
+ ];
+ }
+
+ /**
+ * @dataProvider baseUrlProvider
+ */
+ public function testBaseUrl($kirbyUrl, $url, $expected)
+ {
+ $app = new App([
+ 'roots' => [
+ 'index' => '/dev/null'
+ ],
+ 'urls' => [
+ 'index' => $kirbyUrl
+ ]
+ ]);
+
+ // default
+ $language = new Language([
+ 'code' => 'en',
+ 'url' => $url
+ ]);
+
+ $this->assertEquals($expected, $language->baseUrl());
+ }
}
diff --git a/tests/Cms/Languages/LanguagesTest.php b/tests/Cms/Languages/LanguagesTest.php
index 39537d0238..4f6de69b00 100644
--- a/tests/Cms/Languages/LanguagesTest.php
+++ b/tests/Cms/Languages/LanguagesTest.php
@@ -8,6 +8,9 @@
class LanguagesTest extends TestCase
{
+ protected $app;
+ protected $languages;
+
public function setUp(): void
{
$this->app = new App([
@@ -67,7 +70,6 @@ public function testLoadFromFiles()
public function testDefault()
{
$this->assertEquals('en', $this->languages->default()->code());
- $this->assertEquals('en', $this->languages->findDefault()->code());
}
public function testMultipleDefault()
diff --git a/tests/Cms/Media/MediaTest.php b/tests/Cms/Media/MediaTest.php
index 72ce87407b..86792c9cdf 100644
--- a/tests/Cms/Media/MediaTest.php
+++ b/tests/Cms/Media/MediaTest.php
@@ -8,6 +8,9 @@
class MediaTest extends TestCase
{
+ protected $app;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Models/ModelWithContentTest.php b/tests/Cms/Models/ModelWithContentTest.php
index 1162b4c88e..3218a04338 100644
--- a/tests/Cms/Models/ModelWithContentTest.php
+++ b/tests/Cms/Models/ModelWithContentTest.php
@@ -19,6 +19,11 @@ public function contentFileName(): string
return 'test.txt';
}
+ public function permissions()
+ {
+ return null;
+ }
+
public function root(): ?string
{
return '/tmp';
diff --git a/tests/Cms/Pages/PageChildrenTest.php b/tests/Cms/Pages/PageChildrenTest.php
index 559f51ab4c..df39b61f39 100644
--- a/tests/Cms/Pages/PageChildrenTest.php
+++ b/tests/Cms/Pages/PageChildrenTest.php
@@ -62,7 +62,6 @@ public function testHasListedChildren()
]);
$this->assertTrue($page->hasListedChildren());
- $this->assertTrue($page->hasVisibleChildren());
}
public function testHasNoListedChildren()
@@ -75,7 +74,6 @@ public function testHasNoListedChildren()
]);
$this->assertFalse($page->hasListedChildren());
- $this->assertFalse($page->hasVisibleChildren());
}
public function testHasUnlistedChildren()
@@ -88,7 +86,6 @@ public function testHasUnlistedChildren()
]);
$this->assertTrue($page->hasUnlistedChildren());
- $this->assertTrue($page->hasInvisibleChildren());
}
public function testHasNoUnlistedChildren()
@@ -101,7 +98,6 @@ public function testHasNoUnlistedChildren()
]);
$this->assertFalse($page->hasUnlistedChildren());
- $this->assertFalse($page->hasInvisibleChildren());
}
public function testHasDrafts()
diff --git a/tests/Cms/Pages/PageFilesTest.php b/tests/Cms/Pages/PageFilesTest.php
index 372080c864..c040cb05e8 100644
--- a/tests/Cms/Pages/PageFilesTest.php
+++ b/tests/Cms/Pages/PageFilesTest.php
@@ -4,6 +4,9 @@
class PageFilesTest extends TestCase
{
+ protected $app;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Pages/PagePermissionsTest.php b/tests/Cms/Pages/PagePermissionsTest.php
index 60286d4923..3f07665aa1 100644
--- a/tests/Cms/Pages/PagePermissionsTest.php
+++ b/tests/Cms/Pages/PagePermissionsTest.php
@@ -6,6 +6,8 @@
class PagePermissionsTest extends TestCase
{
+ protected $kirby;
+
public function setUp(): void
{
$this->kirby = new App([
diff --git a/tests/Cms/Pages/PagePickerTest.php b/tests/Cms/Pages/PagePickerTest.php
new file mode 100644
index 0000000000..96888b23ec
--- /dev/null
+++ b/tests/Cms/Pages/PagePickerTest.php
@@ -0,0 +1,100 @@
+app = new App([
+ 'roots' => [
+ 'index' => '/dev/null'
+ ],
+ 'site' => [
+ 'children' => [
+ [
+ 'slug' => 'grandmother',
+ 'children' => [
+ [
+ 'slug' => 'mother',
+ 'children' => [
+ ['slug' => 'child-a'],
+ ['slug' => 'child-b'],
+ ['slug' => 'child-c']
+ ]
+ ]
+ ]
+ ]
+ ]
+ ]
+ ]);
+
+ $this->app->impersonate('kirby');
+ }
+
+ public function testDefaults()
+ {
+ $picker = new PagePicker();
+
+ $this->assertEquals($this->app->site(), $picker->model());
+ $this->assertCount(1, $picker->items());
+ $this->assertEquals('grandmother', $picker->items()->first()->id());
+ }
+
+ public function testParent()
+ {
+ $picker = new PagePicker([
+ 'parent' => 'grandmother'
+ ]);
+
+ $this->assertCount(1, $picker->items());
+ $this->assertEquals('grandmother/mother', $picker->items()->first()->id());
+ $this->assertEquals('grandmother', $picker->model()->id());
+ }
+
+ public function testParentStart()
+ {
+ $picker = new PagePicker([
+ 'parent' => 'grandmother/mother'
+ ]);
+
+ $this->assertEquals($picker->start(), $this->app->site());
+ }
+
+ public function testQuery()
+ {
+ $picker = new PagePicker([
+ 'query' => 'site.find("grandmother/mother").children'
+ ]);
+
+ $this->assertCount(3, $picker->items());
+ $this->assertEquals('grandmother/mother/child-a', $picker->items()->first()->id());
+ $this->assertEquals('grandmother/mother/child-c', $picker->items()->last()->id());
+ }
+
+ public function testQueryAndParent()
+ {
+ $picker = new PagePicker([
+ 'query' => 'site.find("grandmother").children',
+ 'parent' => 'grandmother/mother'
+ ]);
+
+ $this->assertCount(3, $picker->items());
+ $this->assertEquals('grandmother/mother/child-a', $picker->items()->first()->id());
+ $this->assertEquals('grandmother/mother/child-c', $picker->items()->last()->id());
+ }
+
+ public function testQueryStart()
+ {
+ $picker = new PagePicker([
+ 'query' => 'site.find("grandmother").children',
+ 'parent' => 'grandmother/mother'
+ ]);
+
+ $this->assertEquals('grandmother', $picker->start()->id());
+ }
+}
diff --git a/tests/Cms/Pages/PageSiblingsTest.php b/tests/Cms/Pages/PageSiblingsTest.php
index de96f5ff8e..858620cd14 100644
--- a/tests/Cms/Pages/PageSiblingsTest.php
+++ b/tests/Cms/Pages/PageSiblingsTest.php
@@ -6,6 +6,8 @@
class PageSiblingsTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
@@ -59,9 +61,7 @@ public function testHasNextListed()
$collection = $site->children();
$this->assertTrue($collection->first()->hasNextListed());
- $this->assertTrue($collection->first()->hasNextVisible());
$this->assertFalse($collection->last()->hasNextListed());
- $this->assertFalse($collection->last()->hasNextVisible());
}
public function testHasNextUnlisted()
@@ -74,9 +74,7 @@ public function testHasNextUnlisted()
$collection = $site->children();
$this->assertTrue($collection->first()->hasNextUnlisted());
- $this->assertTrue($collection->first()->hasNextInvisible());
$this->assertFalse($collection->last()->hasNextUnlisted());
- $this->assertFalse($collection->last()->hasNextInvisible());
}
public function testHasPrev()
@@ -97,9 +95,7 @@ public function testHasPrevListed()
$collection = $site->children();
$this->assertFalse($collection->first()->hasPrevListed());
- $this->assertFalse($collection->first()->hasPrevVisible());
$this->assertTrue($collection->last()->hasPrevListed());
- $this->assertTrue($collection->last()->hasPrevVisible());
}
public function testHasPrevUnlisted()
@@ -112,9 +108,7 @@ public function testHasPrevUnlisted()
$collection = $site->children();
$this->assertFalse($collection->first()->hasPrevUnlisted());
- $this->assertFalse($collection->first()->hasPrevInvisible());
$this->assertTrue($collection->last()->hasPrevUnlisted());
- $this->assertTrue($collection->last()->hasPrevInvisible());
}
public function testIndexOf()
@@ -178,7 +172,6 @@ public function testNextListed()
])->children();
$this->assertEquals('listed', $collection->first()->nextListed()->slug());
- $this->assertEquals('listed', $collection->first()->nextVisible()->slug());
}
public function testNextUnlisted()
@@ -190,7 +183,6 @@ public function testNextUnlisted()
])->children();
$this->assertEquals('unlisted', $collection->first()->nextUnlisted()->slug());
- $this->assertEquals('unlisted', $collection->first()->nextInvisible()->slug());
}
public function testPrev()
@@ -220,7 +212,6 @@ public function testPrevListed()
])->children();
$this->assertEquals('listed', $collection->last()->prevListed()->slug());
- $this->assertEquals('listed', $collection->last()->prevVisible()->slug());
}
public function testPrevUnlisted()
@@ -232,7 +223,6 @@ public function testPrevUnlisted()
])->children();
$this->assertEquals('unlisted', $collection->last()->prevUnlisted()->slug());
- $this->assertEquals('unlisted', $collection->last()->prevInvisible()->slug());
}
public function testSiblings()
diff --git a/tests/Cms/Pages/PageStatesTest.php b/tests/Cms/Pages/PageStatesTest.php
index 51a960f395..a08b082f10 100644
--- a/tests/Cms/Pages/PageStatesTest.php
+++ b/tests/Cms/Pages/PageStatesTest.php
@@ -20,16 +20,18 @@ public function setUp(): void
public function family()
{
- return new Site([
- 'children' => [
- [
- 'slug' => 'grandma',
- 'children' => [
- [
- 'slug' => 'mother',
- 'children' => [
- [
- 'slug' => 'child'
+ $app = new App([
+ 'site' => [
+ 'children' => [
+ [
+ 'slug' => 'grandma',
+ 'children' => [
+ [
+ 'slug' => 'mother',
+ 'children' => [
+ [
+ 'slug' => 'child'
+ ]
]
]
]
@@ -37,6 +39,8 @@ public function family()
]
]
]);
+
+ return $app->site();
}
public function testIs()
@@ -84,9 +88,13 @@ public function testIsChildOf()
$mother = $grandma->find('mother');
$child = $mother->find('child');
- $this->assertFalse($grandma->isChildOf($mother));
$this->assertTrue($mother->isChildOf($grandma));
$this->assertTrue($child->isChildOf($mother));
+ $this->assertTrue($child->isChildOf($mother->id()));
+ $this->assertFalse($grandma->isChildOf($mother));
+ $this->assertFalse($child->isChildOf($grandma));
+ $this->assertFalse($child->isChildOf('gibberish'));
+ $this->assertFalse($child->isChildOf(null));
}
public function testIsDescendantOf()
@@ -125,14 +133,12 @@ public function testIsListed()
]);
$this->assertTrue($page->isListed());
- $this->assertTrue($page->isVisible());
$page = new Page([
'slug' => 'test',
]);
$this->assertFalse($page->isListed());
- $this->assertFalse($page->isVisible());
}
public function testIsUnlisted()
@@ -142,7 +148,6 @@ public function testIsUnlisted()
]);
$this->assertTrue($page->isUnlisted());
- $this->assertTrue($page->isInvisible());
$page = new Page([
'slug' => 'test',
@@ -150,7 +155,6 @@ public function testIsUnlisted()
]);
$this->assertFalse($page->isUnlisted());
- $this->assertFalse($page->isInvisible());
}
public function testIsDraft()
diff --git a/tests/Cms/Pages/PageTemplateTest.php b/tests/Cms/Pages/PageTemplateTest.php
index 929d54d50b..434e2c9c1a 100644
--- a/tests/Cms/Pages/PageTemplateTest.php
+++ b/tests/Cms/Pages/PageTemplateTest.php
@@ -6,6 +6,8 @@
class PageTemplateTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Pages/PageTest.php b/tests/Cms/Pages/PageTest.php
index 07bd28fcba..379049a232 100644
--- a/tests/Cms/Pages/PageTest.php
+++ b/tests/Cms/Pages/PageTest.php
@@ -8,6 +8,14 @@ class PageTestModel extends Page
{
}
+class PageTestForceLocked extends Page
+{
+ public function isLocked(): bool
+ {
+ return true;
+ }
+}
+
class PageTest extends TestCase
{
@@ -63,7 +71,7 @@ public function testBlueprints()
]
]);
- $this->assertEquals(['A', 'B', 'C'], array_column($page->blueprints(), 'title'));
+ $this->assertEquals(['C', 'A', 'B'], array_column($page->blueprints(), 'title'));
// including the same blueprint
$page = new Page([
@@ -846,6 +854,74 @@ public function testPanelIconWithEmoji()
$this->assertEquals(null, $icon['ratio']);
}
+ public function testPanelOptions()
+ {
+ $page = new Page([
+ 'slug' => 'test',
+ ]);
+
+ $page->kirby()->impersonate('kirby');
+
+ $expected = [
+ 'changeSlug' => true,
+ 'changeStatus' => true,
+ 'changeTemplate' => false, // no other template available in this scenario
+ 'changeTitle' => true,
+ 'create' => true,
+ 'delete' => true,
+ 'duplicate' => true,
+ 'read' => true,
+ 'preview' => true,
+ 'sort' => false, // drafts cannot be sorted
+ 'update' => true,
+ ];
+
+ $this->assertEquals($expected, $page->panelOptions());
+ }
+
+ public function testPanelOptionsWithLockedPage()
+ {
+ $page = new PageTestForceLocked([
+ 'slug' => 'test',
+ ]);
+
+ $page->kirby()->impersonate('kirby');
+
+ // without override
+ $expected = [
+ 'changeSlug' => false,
+ 'changeStatus' => false,
+ 'changeTemplate' => false,
+ 'changeTitle' => false,
+ 'create' => false,
+ 'delete' => false,
+ 'duplicate' => false,
+ 'read' => false,
+ 'preview' => false,
+ 'sort' => false,
+ 'update' => false,
+ ];
+
+ $this->assertEquals($expected, $page->panelOptions());
+
+ // with override
+ $expected = [
+ 'changeSlug' => false,
+ 'changeStatus' => false,
+ 'changeTemplate' => false,
+ 'changeTitle' => false,
+ 'create' => false,
+ 'delete' => false,
+ 'duplicate' => false,
+ 'read' => false,
+ 'preview' => true,
+ 'sort' => false,
+ 'update' => false,
+ ];
+
+ $this->assertEquals($expected, $page->panelOptions(['preview']));
+ }
+
public function testPanelUrl()
{
$app = new App([
diff --git a/tests/Cms/Pages/PageTestCase.php b/tests/Cms/Pages/PageTestCase.php
index 443990b6b0..24a2273bab 100644
--- a/tests/Cms/Pages/PageTestCase.php
+++ b/tests/Cms/Pages/PageTestCase.php
@@ -6,24 +6,24 @@ class PageTestCase extends TestCase
{
public $page = null;
- public function page($id = null)
+ public function page(?string $id = null)
{
return parent::page($id ?? $this->page);
}
public function assertPageTitle(string $title)
{
- return $this->assertPageField('title', $title);
+ $this->assertPageField('title', $title);
}
public function assertPageSlug(string $slug)
{
- return $this->assertEquals($slug, $this->page()->slug());
+ $this->assertEquals($slug, $this->page()->slug());
}
public function assertPageTemplate(string $template)
{
- return $this->assertEquals($template, $this->page()->template());
+ $this->assertEquals($template, $this->page()->template());
}
public function assertPageField(string $key, string $value)
diff --git a/tests/Cms/Pages/PagesTest.php b/tests/Cms/Pages/PagesTest.php
index 797d029572..a03f1a8f54 100644
--- a/tests/Cms/Pages/PagesTest.php
+++ b/tests/Cms/Pages/PagesTest.php
@@ -78,6 +78,36 @@ public function testAddById()
$this->assertEquals('a/aa', $pages->nth(2)->id());
}
+ public function testAddNull()
+ {
+ $pages = new Pages();
+ $this->assertCount(0, $pages);
+
+ $pages->add(null);
+
+ $this->assertCount(0, $pages);
+ }
+
+ public function testAddFalse()
+ {
+ $pages = new Pages();
+ $this->assertCount(0, $pages);
+
+ $pages->add(false);
+
+ $this->assertCount(0, $pages);
+ }
+
+ public function testAddInvalidObject()
+ {
+ $this->expectException('Kirby\Exception\InvalidArgumentException');
+ $this->expectExceptionMessage('You must pass a Page object to the Pages collection');
+
+ $site = new Site();
+ $pages = new Pages();
+ $pages->add($site);
+ }
+
public function testAudio()
{
$pages = Pages::factory([
@@ -402,6 +432,34 @@ public function testIndexWithDrafts()
$this->assertEquals($expected, $pages->index(true)->keys());
}
+ public function testNotTemplate()
+ {
+ $pages = Pages::factory([
+ [
+ 'slug' => 'a',
+ 'template' => 'a'
+ ],
+ [
+ 'slug' => 'b',
+ 'template' => 'b'
+ ],
+ [
+ 'slug' => 'c',
+ 'template' => 'c'
+ ],
+ [
+ 'slug' => 'd',
+ 'template' => 'a'
+ ],
+ ]);
+
+ $this->assertEquals(['a', 'b', 'c', 'd'], $pages->notTemplate(null)->pluck('slug'));
+ $this->assertEquals(['b', 'c'], $pages->notTemplate('a')->pluck('slug'));
+ $this->assertEquals(['c'], $pages->notTemplate(['a', 'b'])->pluck('slug'));
+ $this->assertEquals(['a', 'b', 'c', 'd'], $pages->notTemplate(['z'])->pluck('slug'));
+ $this->assertEquals([], $pages->notTemplate(['a', 'b', 'c'])->pluck('slug'));
+ }
+
public function testNums()
{
$pages = Pages::factory([
diff --git a/tests/Cms/Plugins/PanelPluginsTest.php b/tests/Cms/Plugins/PanelPluginsTest.php
index d66fe23048..59d948b9a7 100644
--- a/tests/Cms/Plugins/PanelPluginsTest.php
+++ b/tests/Cms/Plugins/PanelPluginsTest.php
@@ -8,6 +8,13 @@
class PanelPluginsTest extends TestCase
{
+ protected $app;
+ protected $fixtures;
+ protected $cssA;
+ protected $cssB;
+ protected $jsA;
+ protected $jsB;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Plugins/PluginAssetsTest.php b/tests/Cms/Plugins/PluginAssetsTest.php
index c26decd90b..e1a26e1ecc 100644
--- a/tests/Cms/Plugins/PluginAssetsTest.php
+++ b/tests/Cms/Plugins/PluginAssetsTest.php
@@ -8,6 +8,9 @@
class PluginAssetsTest extends TestCase
{
+ protected $app;
+ protected $fixtures;
+
public function setUp(): void
{
$this->fixtures = __DIR__ . '/fixtures/PluginAssetsTest';
diff --git a/tests/Cms/Routes/RouterTest.php b/tests/Cms/Routes/RouterTest.php
index 8051199a5d..ee9c084c53 100644
--- a/tests/Cms/Routes/RouterTest.php
+++ b/tests/Cms/Routes/RouterTest.php
@@ -9,6 +9,7 @@
class RouterTest extends TestCase
{
protected $app;
+ protected $fixtures;
public function setUp(): void
{
@@ -409,7 +410,8 @@ public function testMultiLangHomeRouteWithoutLanguageCode()
],
[
'code' => 'en',
- ]
+ 'url' => '/en'
+ ],
]
]);
@@ -430,6 +432,100 @@ public function testMultiLangHomeRouteWithoutLanguageCode()
$this->assertEquals('en', I18n::locale());
}
+ public function multiDomainProvider()
+ {
+ return [
+ ['https://getkirby.fr', 'fr'],
+ ['https://getkirby.com', 'en'],
+ ];
+ }
+
+ /**
+ * @dataProvider multiDomainProvider
+ */
+ public function testMultiLangHomeWithDifferentDomains($domain, $language)
+ {
+ $app = $this->app->clone([
+ 'urls' => [
+ 'index' => $domain
+ ],
+ 'site' => [
+ 'children' => [
+ [
+ 'slug' => 'home'
+ ]
+ ]
+ ],
+ 'options' => [
+ 'languages' => true
+ ],
+ 'languages' => [
+ [
+ 'code' => 'fr',
+ 'default' => true,
+ 'url' => 'https://getkirby.fr'
+ ],
+ [
+ 'code' => 'en',
+ 'url' => 'https://getkirby.com'
+ ]
+ ]
+ ]);
+
+ // home
+ $page = $app->call('');
+
+ $this->assertInstanceOf(Page::class, $page);
+ $this->assertEquals('home', $page->id());
+ $this->assertEquals($language, $app->language()->code());
+ $this->assertEquals($language, I18n::locale());
+ }
+
+ /**
+ * @dataProvider multiDomainProvider
+ */
+ public function testMultiLangHomeWithDifferentDomainsAndPath($domain, $language)
+ {
+ $app = $this->app->clone([
+ 'urls' => [
+ 'index' => $domain
+ ],
+ 'site' => [
+ 'children' => [
+ [
+ 'slug' => 'home'
+ ]
+ ]
+ ],
+ 'options' => [
+ 'languages' => true
+ ],
+ 'languages' => [
+ [
+ 'code' => 'fr',
+ 'default' => true,
+ 'url' => 'https://getkirby.fr/subfolder'
+ ],
+ [
+ 'code' => 'en',
+ 'url' => 'https://getkirby.com/subfolder'
+ ]
+ ]
+ ]);
+
+ // redirect
+ $redirect = $app->call('');
+ $this->assertInstanceOf(Responder::class, $redirect);
+
+ // home
+ $page = $app->call('subfolder');
+
+ $this->assertInstanceOf(Page::class, $page);
+ $this->assertEquals('home', $page->id());
+ $this->assertEquals($language, $app->language()->code());
+ $this->assertEquals($language, I18n::locale());
+ }
+
public function acceptedLanguageProvider()
{
return [
@@ -471,6 +567,7 @@ public function testMultiLangHomeRouteWithoutLanguageCodeAndLanguageDetection($a
// set the accepted visitor language
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = $accept;
+ $app = $app->clone();
$response = $app->call('/');
diff --git a/tests/Cms/Sections/FieldsSectionTest.php b/tests/Cms/Sections/FieldsSectionTest.php
index d1333a962c..01e71fc48a 100644
--- a/tests/Cms/Sections/FieldsSectionTest.php
+++ b/tests/Cms/Sections/FieldsSectionTest.php
@@ -6,6 +6,8 @@
class FieldsSectionTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
App::destroy();
diff --git a/tests/Cms/Sections/FilesSectionTest.php b/tests/Cms/Sections/FilesSectionTest.php
index 69ea4cb4c8..f6800eb57f 100644
--- a/tests/Cms/Sections/FilesSectionTest.php
+++ b/tests/Cms/Sections/FilesSectionTest.php
@@ -6,6 +6,8 @@
class FilesSectionTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
App::destroy();
@@ -228,7 +230,6 @@ public function testDragTextWithDifferentParent()
public function testHelp()
{
-
// single help
$section = new Section('files', [
'name' => 'test',
@@ -236,7 +237,7 @@ public function testHelp()
'help' => 'Test'
]);
- $this->assertEquals('Test', $section->help());
+ $this->assertEquals('Test
', $section->help());
// translated help
$section = new Section('files', [
@@ -248,7 +249,7 @@ public function testHelp()
]
]);
- $this->assertEquals('Information', $section->help());
+ $this->assertEquals('Information
', $section->help());
}
public function testSortBy()
@@ -344,4 +345,32 @@ public function testDisableSortableWhenSortBy()
$this->assertFalse($section->sortable());
}
+
+ public function testFlip()
+ {
+ $model = new Page([
+ 'slug' => 'test',
+ 'files' => [
+ [
+ 'filename' => 'c.jpg'
+ ],
+ [
+ 'filename' => 'a.jpg'
+ ],
+ [
+ 'filename' => 'b.jpg'
+ ]
+ ]
+ ]);
+
+ $section = new Section('files', [
+ 'name' => 'test',
+ 'model' => $model,
+ 'flip' => true
+ ]);
+
+ $this->assertEquals('c.jpg', $section->data()[0]['filename']);
+ $this->assertEquals('b.jpg', $section->data()[1]['filename']);
+ $this->assertEquals('a.jpg', $section->data()[2]['filename']);
+ }
}
diff --git a/tests/Cms/Sections/InfoSectionTest.php b/tests/Cms/Sections/InfoSectionTest.php
index 147507f88d..9d7b695d0c 100644
--- a/tests/Cms/Sections/InfoSectionTest.php
+++ b/tests/Cms/Sections/InfoSectionTest.php
@@ -6,6 +6,8 @@
class InfoSectionTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
App::destroy();
diff --git a/tests/Cms/Sections/PagesSectionTest.php b/tests/Cms/Sections/PagesSectionTest.php
index 5e5f0fe056..16200a792d 100644
--- a/tests/Cms/Sections/PagesSectionTest.php
+++ b/tests/Cms/Sections/PagesSectionTest.php
@@ -6,6 +6,8 @@
class PagesSectionTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
App::destroy();
@@ -239,6 +241,28 @@ public function testDisableSortable()
$this->assertFalse($section->sortable());
}
+ public function testFlip()
+ {
+ $page = new Page([
+ 'slug' => 'test',
+ 'children' => [
+ ['slug' => 'subpage-1', 'content' => ['title' => 'C']],
+ ['slug' => 'subpage-2', 'content' => ['title' => 'A']],
+ ['slug' => 'subpage-3', 'content' => ['title' => 'B']]
+ ]
+ ]);
+
+ $section = new Section('pages', [
+ 'name' => 'test',
+ 'model' => $page,
+ 'flip' => true
+ ]);
+
+ $this->assertEquals('B', $section->data()[0]['text']);
+ $this->assertEquals('A', $section->data()[1]['text']);
+ $this->assertEquals('C', $section->data()[2]['text']);
+ }
+
public function sortableStatusProvider()
{
return [
@@ -366,7 +390,7 @@ public function testHelp()
'help' => 'Test'
]);
- $this->assertEquals('Test', $section->help());
+ $this->assertEquals('Test
', $section->help());
// translated help
$section = new Section('pages', [
@@ -378,6 +402,6 @@ public function testHelp()
]
]);
- $this->assertEquals('Information', $section->help());
+ $this->assertEquals('Information
', $section->help());
}
}
diff --git a/tests/Cms/Sections/SectionTest.php b/tests/Cms/Sections/SectionTest.php
index 29177c9a07..1b15e568a0 100644
--- a/tests/Cms/Sections/SectionTest.php
+++ b/tests/Cms/Sections/SectionTest.php
@@ -6,6 +6,8 @@
class SectionTest extends TestCase
{
+ protected $app;
+
public function setUp(): void
{
App::destroy();
@@ -60,9 +62,9 @@ public function testToResponse()
'a' => function ($a) {
return $a;
},
- 'a' => function ($b) {
+ 'b' => function ($b) {
return $b;
- },
+ }
]
]
];
diff --git a/tests/Cms/Sections/mixins/EmptySectionMixinTest.php b/tests/Cms/Sections/mixins/EmptySectionMixinTest.php
index 0d112d40f4..883bbd1ee4 100644
--- a/tests/Cms/Sections/mixins/EmptySectionMixinTest.php
+++ b/tests/Cms/Sections/mixins/EmptySectionMixinTest.php
@@ -6,6 +6,9 @@
class EmptySectionMixinTest extends TestCase
{
+ protected $app;
+ protected $page;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Sections/mixins/MaxSectionMixinTest.php b/tests/Cms/Sections/mixins/MaxSectionMixinTest.php
index f3999caa12..34eac4f7ea 100644
--- a/tests/Cms/Sections/mixins/MaxSectionMixinTest.php
+++ b/tests/Cms/Sections/mixins/MaxSectionMixinTest.php
@@ -6,6 +6,9 @@
class MaxSectionMixinTest extends TestCase
{
+ protected $app;
+ protected $page;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/Sections/mixins/MinSectionMixinTest.php b/tests/Cms/Sections/mixins/MinSectionMixinTest.php
index 0f88b11dc2..2d39bfe9ca 100644
--- a/tests/Cms/Sections/mixins/MinSectionMixinTest.php
+++ b/tests/Cms/Sections/mixins/MinSectionMixinTest.php
@@ -6,6 +6,9 @@
class MinSectionMixinTest extends TestCase
{
+ protected $app;
+ protected $page;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Cms/System/SystemTest.php b/tests/Cms/System/SystemTest.php
index 2cfaa83a7c..8bccdbcbf9 100644
--- a/tests/Cms/System/SystemTest.php
+++ b/tests/Cms/System/SystemTest.php
@@ -8,6 +8,8 @@
class SystemTest extends TestCase
{
protected $_SERVER = null;
+ protected $app;
+ protected $fixtures;
public function setUp(): void
{
diff --git a/tests/Cms/Users/UserPickerTest.php b/tests/Cms/Users/UserPickerTest.php
new file mode 100644
index 0000000000..a2cb3507a6
--- /dev/null
+++ b/tests/Cms/Users/UserPickerTest.php
@@ -0,0 +1,42 @@
+app = new App([
+ 'roots' => [
+ 'index' => '/dev/null'
+ ],
+ 'users' => [
+ ['email' => 'a@getkirby.com'],
+ ['email' => 'b@getkirby.com'],
+ ['email' => 'c@getkirby.com']
+ ]
+ ]);
+
+ $this->app->impersonate('kirby');
+ }
+
+ public function testDefaults()
+ {
+ $picker = new UserPicker();
+
+ $this->assertCount(3, $picker->items());
+ }
+
+ public function testQuery()
+ {
+ $picker = new UserPicker([
+ 'query' => 'kirby.users.offset(1)'
+ ]);
+
+ $this->assertCount(2, $picker->items());
+ }
+}
diff --git a/tests/Cms/Users/UserTest.php b/tests/Cms/Users/UserTest.php
index 5990b809b0..3c50183a31 100644
--- a/tests/Cms/Users/UserTest.php
+++ b/tests/Cms/Users/UserTest.php
@@ -8,6 +8,14 @@ class UserTestModel extends User
{
}
+class UserTestForceLocked extends User
+{
+ public function isLocked(): bool
+ {
+ return true;
+ }
+}
+
class UserTest extends TestCase
{
public function testAvatar()
@@ -239,4 +247,122 @@ public function testUserModel()
User::$models = [];
}
+
+ public function testLoginLogoutHooks()
+ {
+ $phpunit = $this;
+
+ $calls = 0;
+ $logoutSession = false;
+ $app = new App([
+ 'users' => [
+ ['email' => 'test@getkirby.com']
+ ],
+ 'hooks' => [
+ 'user.login:before' => function ($user, $session) use ($phpunit, &$calls) {
+ $phpunit->assertEquals('test@getkirby.com', $user->email());
+ $phpunit->assertEquals($session, S::instance());
+
+ $calls += 1;
+ },
+ 'user.login:after' => function ($user, $session) use ($phpunit, &$calls) {
+ $phpunit->assertEquals('test@getkirby.com', $user->email());
+ $phpunit->assertEquals($session, S::instance());
+
+ $calls += 2;
+ },
+ 'user.logout:before' => function ($user, $session) use ($phpunit, &$calls) {
+ $phpunit->assertEquals('test@getkirby.com', $user->email());
+ $phpunit->assertEquals($session, S::instance());
+
+ $calls += 4;
+ },
+ 'user.logout:after' => function ($user, $session) use ($phpunit, &$calls, &$logoutSession) {
+ $phpunit->assertEquals('test@getkirby.com', $user->email());
+
+ if ($logoutSession === true) {
+ $phpunit->assertEquals($session, S::instance());
+ $phpunit->assertEquals('value', S::instance()->get('some'));
+ } else {
+ $phpunit->assertNull($session);
+ }
+
+ $calls += 8;
+ }
+ ]
+ ]);
+
+ // without prepopulated session
+ $user = $app->user('test@getkirby.com');
+ $user->loginPasswordless();
+ $user->logout();
+
+ // with a session with another value
+ S::instance()->set('some', 'value');
+ $logoutSession = true;
+ $user->loginPasswordless();
+ $user->logout();
+
+ // each hook needs to be called exactly twice
+ $this->assertEquals((1 + 2 + 4 + 8) * 2, $calls);
+ }
+
+ public function testPanelOptions()
+ {
+ $user = new User([
+ 'email' => 'test@getkirby.com',
+ ]);
+
+ $user->kirby()->impersonate('kirby');
+
+ $expected = [
+ 'create' => true,
+ 'changeEmail' => true,
+ 'changeLanguage' => true,
+ 'changeName' => true,
+ 'changePassword' => true,
+ 'changeRole' => false, // just one role
+ 'delete' => true,
+ 'update' => true,
+ ];
+
+ $this->assertEquals($expected, $user->panelOptions());
+ }
+
+ public function testPanelOptionsWithLockedUser()
+ {
+ $user = new UserTestForceLocked([
+ 'email' => 'test@getkirby.com',
+ ]);
+
+ $user->kirby()->impersonate('kirby');
+
+ // without override
+ $expected = [
+ 'create' => false,
+ 'changeEmail' => false,
+ 'changeLanguage' => false,
+ 'changeName' => false,
+ 'changePassword' => false,
+ 'changeRole' => false,
+ 'delete' => false,
+ 'update' => false,
+ ];
+
+ $this->assertEquals($expected, $user->panelOptions());
+
+ // with override
+ $expected = [
+ 'create' => false,
+ 'changeEmail' => true,
+ 'changeLanguage' => false,
+ 'changeName' => false,
+ 'changePassword' => false,
+ 'changeRole' => false,
+ 'delete' => false,
+ 'update' => false,
+ ];
+
+ $this->assertEquals($expected, $user->panelOptions(['changeEmail']));
+ }
}
diff --git a/tests/Cms/mocks.php b/tests/Cms/mocks.php
index 46e5cc5380..e77ef7fcf1 100644
--- a/tests/Cms/mocks.php
+++ b/tests/Cms/mocks.php
@@ -2,6 +2,8 @@
namespace Kirby\Cms;
+use Exception;
+
/**
* Mock for the PHP time() function to ensure reliable testing
*
diff --git a/tests/Data/DataTest.php b/tests/Data/DataTest.php
index 213a69cc8a..0f96bbb981 100644
--- a/tests/Data/DataTest.php
+++ b/tests/Data/DataTest.php
@@ -78,7 +78,7 @@ public function testEncodeDecode()
$encoded = Data::encode($data, $handler);
$decoded = Data::decode($encoded, $handler);
- $this->assertEquals($data, $decoded);
+ $this->assertSame($data, $decoded);
}
}
@@ -97,18 +97,18 @@ public function testReadWrite()
// automatic type detection
Data::write($file, $data);
$this->assertFileExists($file);
- $this->assertEquals(Json::encode($data), F::read($file));
+ $this->assertSame(Json::encode($data), F::read($file));
$result = Data::read($file);
- $this->assertEquals($data, $result);
+ $this->assertSame($data, $result);
// custom type
Data::write($file, $data, 'yml');
$this->assertFileExists($file);
- $this->assertEquals(Yaml::encode($data), F::read($file));
+ $this->assertSame(Yaml::encode($data), F::read($file));
$result = Data::read($file, 'yml');
- $this->assertEquals($data, $result);
+ $this->assertSame($data, $result);
}
/**
diff --git a/tests/Data/HandlerTest.php b/tests/Data/HandlerTest.php
index 72e8bd7195..61794f87b0 100644
--- a/tests/Data/HandlerTest.php
+++ b/tests/Data/HandlerTest.php
@@ -30,10 +30,10 @@ public function testReadWrite()
CustomHandler::write($file, $data);
$this->assertFileExists($file);
- $this->assertEquals(CustomHandler::encode($data), F::read($file));
+ $this->assertSame(CustomHandler::encode($data), F::read($file));
$result = CustomHandler::read($file);
- $this->assertEquals($data, $result);
+ $this->assertSame($data, $result);
}
/**
diff --git a/tests/Data/JsonTest.php b/tests/Data/JsonTest.php
index 7ba9d70840..405452ab3f 100644
--- a/tests/Data/JsonTest.php
+++ b/tests/Data/JsonTest.php
@@ -21,10 +21,10 @@ public function testEncodeDecode()
];
$data = Json::encode($array);
- $this->assertEquals('{"name":"Homer","children":["Lisa","Bart","Maggie"]}', $data);
+ $this->assertSame('{"name":"Homer","children":["Lisa","Bart","Maggie"]}', $data);
$result = Json::decode($data);
- $this->assertEquals($array, $result);
+ $this->assertSame($array, $result);
}
/**
@@ -33,7 +33,7 @@ public function testEncodeDecode()
public function testEncodeUnicode()
{
$string = 'здравей';
- $this->assertEquals('"' . $string . '"', Json::encode($string));
+ $this->assertSame('"' . $string . '"', Json::encode($string));
}
/**
diff --git a/tests/Data/PHPTest.php b/tests/Data/PHPTest.php
index 874e2c5d85..f1238f6611 100644
--- a/tests/Data/PHPTest.php
+++ b/tests/Data/PHPTest.php
@@ -19,7 +19,7 @@ public function testEncode()
$expected = __DIR__ . '/fixtures/php/expected.php';
$result = PHP::encode(include $input);
- $this->assertEquals(trim(file_get_contents($expected)), $result);
+ $this->assertSame(trim(file_get_contents($expected)), $result);
}
/**
@@ -30,7 +30,7 @@ public function testDecode()
$input = include __DIR__ . '/fixtures/php/input.php';
$result = PHP::decode($input);
- $this->assertEquals($input, $result);
+ $this->assertSame($input, $result);
}
/**
@@ -41,7 +41,7 @@ public function testRead()
$input = __DIR__ . '/fixtures/php/input.php';
$result = PHP::read($input);
- $this->assertEquals($result, include $input);
+ $this->assertSame($result, include $input);
}
/**
@@ -67,8 +67,8 @@ public function testWrite()
$this->assertTrue(PHP::write($file, $input));
- $this->assertEquals($input, include $file);
- $this->assertEquals($input, PHP::read($file));
+ $this->assertSame($input, include $file);
+ $this->assertSame($input, PHP::read($file));
F::remove($file);
}
diff --git a/tests/Data/TxtTest.php b/tests/Data/TxtTest.php
index bd497826e7..e801c979bc 100644
--- a/tests/Data/TxtTest.php
+++ b/tests/Data/TxtTest.php
@@ -25,13 +25,13 @@ public function testEncodeDecode()
];
$data = Txt::encode($array);
- $this->assertEquals(
+ $this->assertSame(
"Title: Title\n\n----\n\nText: Text",
$data
);
$result = Txt::decode($data);
- $this->assertEquals($array, $result);
+ $this->assertSame($array, $result);
}
/**
@@ -49,7 +49,7 @@ public function testEncodeMissingValues()
];
$data = Txt::encode($array);
- $this->assertEquals(
+ $this->assertSame(
"Title: Title\n\n----\n\nField: content",
$data
);
@@ -68,7 +68,7 @@ public function testEncodeMultiline()
];
$data = Txt::encode($array);
- $this->assertEquals(
+ $this->assertSame(
"Title: Title\n\n----\n\nText:\n\nText\nText",
$data
);
@@ -87,13 +87,13 @@ public function testEncodeDecodeDivider()
];
$data = Txt::encode($array);
- $this->assertEquals(
+ $this->assertSame(
"Title: Title\n\n----\n\nText:\n\n\\----\n\\----\n" .
"Text\n\n\\----Field:\nValue\n\\---- \n\\----",
$data
);
- $this->assertEquals($array, Txt::decode($data));
+ $this->assertSame($array, Txt::decode($data));
}
/**
@@ -109,7 +109,7 @@ public function testEncodeArray()
];
$data = Txt::encode($array);
- $this->assertEquals(file_get_contents(static::FIXTURES . '/test.txt'), $data);
+ $this->assertSame(file_get_contents(static::FIXTURES . '/test.txt'), $data);
}
/**
@@ -123,7 +123,7 @@ public function testEncodeFloat()
'number' => (float)3.2
]);
- $this->assertEquals('Number: 3.2', $data);
+ $this->assertSame('Number: 3.2', $data);
}
/**
@@ -140,7 +140,7 @@ public function testEncodeFloatWithLocaleSetting()
'number' => (float)3.2
]);
- $this->assertEquals('Number: 3.2', $data);
+ $this->assertSame('Number: 3.2', $data);
setlocale(LC_ALL, $currentLocale);
}
@@ -156,6 +156,6 @@ public function testDecodeFile()
];
$data = Txt::decode(file_get_contents(static::FIXTURES . '/decode.txt'));
- $this->assertEquals($array, $data);
+ $this->assertSame($array, $data);
}
}
diff --git a/tests/Data/YamlTest.php b/tests/Data/YamlTest.php
index fbf389726d..0fe9db3754 100644
--- a/tests/Data/YamlTest.php
+++ b/tests/Data/YamlTest.php
@@ -21,16 +21,16 @@ public function testEncodeDecode()
];
$data = Yaml::encode($array);
- $this->assertEquals(
+ $this->assertSame(
"name: Homer\nchildren:\n - Lisa\n - Bart\n - Maggie\n",
$data
);
$result = Yaml::decode($data);
- $this->assertEquals($array, $result);
+ $this->assertSame($array, $result);
- $this->assertEquals([], Yaml::decode(null));
- $this->assertEquals(['this is' => 'an array'], Yaml::decode(['this is' => 'an array']));
+ $this->assertSame([], Yaml::decode(null));
+ $this->assertSame(['this is' => 'an array'], Yaml::decode(['this is' => 'an array']));
}
/**
@@ -42,7 +42,7 @@ public function testEncodeFloat()
'number' => 3.2
]);
- $this->assertEquals('number: 3.2' . PHP_EOL, $data);
+ $this->assertSame('number: 3.2' . PHP_EOL, $data);
}
/**
@@ -58,7 +58,7 @@ public function testEncodeFloatWithNonUSLocale()
'number' => 3.2
]);
- $this->assertEquals('number: 3.2' . PHP_EOL, $data);
+ $this->assertSame('number: 3.2' . PHP_EOL, $data);
setlocale(LC_ALL, $locale);
}
diff --git a/tests/Database/SqlTest.php b/tests/Database/SqlTest.php
index 41b7424f09..0b9444f984 100644
--- a/tests/Database/SqlTest.php
+++ b/tests/Database/SqlTest.php
@@ -7,6 +7,8 @@
class SqlTest extends TestCase
{
+ protected $database;
+
public function setUp(): void
{
$this->database = new Database([
diff --git a/tests/Exception/BadMethodCallExceptionTest.php b/tests/Exception/BadMethodCallExceptionTest.php
index 669ffc37b1..373b042983 100644
--- a/tests/Exception/BadMethodCallExceptionTest.php
+++ b/tests/Exception/BadMethodCallExceptionTest.php
@@ -12,10 +12,10 @@ class BadMethodCallExceptionTest extends TestCase
public function testDefaults()
{
$exception = new BadMethodCallException();
- $this->assertEquals('error.invalidMethod', $exception->getKey());
- $this->assertEquals('The method "-" does not exist', $exception->getMessage());
- $this->assertEquals(400, $exception->getHttpCode());
- $this->assertEquals(['method' => null], $exception->getData());
+ $this->assertSame('error.invalidMethod', $exception->getKey());
+ $this->assertSame('The method "-" does not exist', $exception->getMessage());
+ $this->assertSame(400, $exception->getHttpCode());
+ $this->assertSame(['method' => null], $exception->getData());
}
/**
@@ -28,7 +28,7 @@ public function testPlaceholders()
'method' => 'get'
]
]);
- $this->assertEquals('The method "get" does not exist', $exception->getMessage());
- $this->assertEquals(['method' => 'get'], $exception->getData());
+ $this->assertSame('The method "get" does not exist', $exception->getMessage());
+ $this->assertSame(['method' => 'get'], $exception->getData());
}
}
diff --git a/tests/Exception/DuplicateExceptionTest.php b/tests/Exception/DuplicateExceptionTest.php
index 94bb596be2..b446a93e60 100644
--- a/tests/Exception/DuplicateExceptionTest.php
+++ b/tests/Exception/DuplicateExceptionTest.php
@@ -12,8 +12,8 @@ class DuplicateExceptionTest extends TestCase
public function testDefaults()
{
$exception = new DuplicateException();
- $this->assertEquals('error.duplicate', $exception->getKey());
- $this->assertEquals('The entry exists', $exception->getMessage());
- $this->assertEquals(400, $exception->getHttpCode());
+ $this->assertSame('error.duplicate', $exception->getKey());
+ $this->assertSame('The entry exists', $exception->getMessage());
+ $this->assertSame(400, $exception->getHttpCode());
}
}
diff --git a/tests/Exception/ErrorPageExceptionTest.php b/tests/Exception/ErrorPageExceptionTest.php
new file mode 100644
index 0000000000..91d264b0ba
--- /dev/null
+++ b/tests/Exception/ErrorPageExceptionTest.php
@@ -0,0 +1,19 @@
+assertEquals('error.errorPage', $exception->getKey());
+ $this->assertEquals('Triggered error page', $exception->getMessage());
+ $this->assertEquals(404, $exception->getHttpCode());
+ }
+}
diff --git a/tests/Exception/ExceptionTest.php b/tests/Exception/ExceptionTest.php
index 2d43c4bce3..b77df8ff73 100644
--- a/tests/Exception/ExceptionTest.php
+++ b/tests/Exception/ExceptionTest.php
@@ -46,12 +46,12 @@ public function testException()
]);
$this->assertInstanceOf(Exception::class, $exception);
- $this->assertEquals('error.page.slug.invalid', $exception->getKey());
- $this->assertEquals('error.page.slug.invalid', $exception->getCode());
- $this->assertEquals('The page slug "project/(c" is invalid', $exception->getMessage());
- $this->assertEquals($http, $exception->getHttpCode());
- $this->assertEquals($data, $exception->getData());
- $this->assertEquals($details, $exception->getDetails());
+ $this->assertSame('error.page.slug.invalid', $exception->getKey());
+ $this->assertSame('error.page.slug.invalid', $exception->getCode());
+ $this->assertSame('The page slug "project/(c" is invalid', $exception->getMessage());
+ $this->assertSame($http, $exception->getHttpCode());
+ $this->assertSame($data, $exception->getData());
+ $this->assertSame($details, $exception->getDetails());
$this->assertFalse($exception->isTranslated());
}
@@ -62,12 +62,12 @@ public function testDefaults()
{
$exception = new Exception();
- $this->assertEquals('error.general', $exception->getKey());
- $this->assertEquals('An error occurred', $exception->getMessage());
- $this->assertEquals(500, $exception->getHttpCode());
+ $this->assertSame('error.general', $exception->getKey());
+ $this->assertSame('An error occurred', $exception->getMessage());
+ $this->assertSame(500, $exception->getHttpCode());
$this->assertFalse($exception->isTranslated());
- $this->assertEquals([], $exception->getData());
- $this->assertEquals([], $exception->getDetails());
+ $this->assertSame([], $exception->getData());
+ $this->assertSame([], $exception->getDetails());
}
/**
@@ -77,11 +77,11 @@ public function testJustMessage()
{
$exception = new Exception('Another error occurred');
- $this->assertEquals('error.general', $exception->getKey());
- $this->assertEquals('Another error occurred', $exception->getMessage());
- $this->assertEquals(500, $exception->getHttpCode());
+ $this->assertSame('error.general', $exception->getKey());
+ $this->assertSame('Another error occurred', $exception->getMessage());
+ $this->assertSame(500, $exception->getHttpCode());
$this->assertFalse($exception->isTranslated());
- $this->assertEquals([], $exception->getData());
+ $this->assertSame([], $exception->getData());
}
/**
@@ -93,7 +93,7 @@ public function testPrevious()
$exception = new Exception(['previous' => $previous]);
$this->assertNull($previous->getPrevious());
- $this->assertEquals($previous, $exception->getPrevious());
+ $this->assertSame($previous, $exception->getPrevious());
}
/**
@@ -126,7 +126,7 @@ public function testTranslation()
'key' => 'translatable',
'fallback' => 'Some fallback'
]);
- $this->assertEquals('Some other translatable error', $exception->getMessage());
+ $this->assertSame('Some other translatable error', $exception->getMessage());
$this->assertTrue($exception->isTranslated());
// scenario 3: provided fallback message
@@ -134,14 +134,14 @@ public function testTranslation()
'key' => 'not-translated',
'fallback' => 'Some fallback'
]);
- $this->assertEquals('Some fallback', $exception->getMessage());
+ $this->assertSame('Some fallback', $exception->getMessage());
$this->assertFalse($exception->isTranslated());
// scenario 4: translation for default key in current language
$exception = new Exception([
'key' => 'not-translated'
]);
- $this->assertEquals('Some general error', $exception->getMessage());
+ $this->assertSame('Some general error', $exception->getMessage());
$this->assertTrue($exception->isTranslated());
I18n::$translations = [
@@ -156,14 +156,14 @@ public function testTranslation()
'key' => 'translatable',
'fallback' => 'Some fallback'
]);
- $this->assertEquals('Some other translatable fallback', $exception->getMessage());
+ $this->assertSame('Some other translatable fallback', $exception->getMessage());
$this->assertTrue($exception->isTranslated());
// scenario 5: translation for default key in default language
$exception = new Exception([
'key' => 'not-translated'
]);
- $this->assertEquals('Some general fallback', $exception->getMessage());
+ $this->assertSame('Some general fallback', $exception->getMessage());
$this->assertTrue($exception->isTranslated());
I18n::$locale = 'en';
@@ -173,7 +173,7 @@ public function testTranslation()
$exception = new Exception([
'key' => 'translatable'
]);
- $this->assertEquals('An error occurred', $exception->getMessage());
+ $this->assertSame('An error occurred', $exception->getMessage());
$this->assertFalse($exception->isTranslated());
}
@@ -183,13 +183,13 @@ public function testTranslation()
public function testGetFileRelative()
{
$exception = new Exception();
- $this->assertEquals(__FILE__, $exception->getFileRelative());
+ $this->assertSame(__FILE__, $exception->getFileRelative());
$_SERVER['DOCUMENT_ROOT'] = __DIR__;
- $this->assertEquals(F::filename(__FILE__), $exception->getFileRelative());
+ $this->assertSame(F::filename(__FILE__), $exception->getFileRelative());
$_SERVER['DOCUMENT_ROOT'] = __DIR__ . '/';
- $this->assertEquals(F::filename(__FILE__), $exception->getFileRelative());
+ $this->assertSame(F::filename(__FILE__), $exception->getFileRelative());
}
/**
@@ -207,12 +207,12 @@ public function testToArray()
'details' => [],
'code' => 500
];
- $this->assertEquals($expected, $exception->toArray());
+ $this->assertSame($expected, $exception->toArray());
$_SERVER['DOCUMENT_ROOT'] = __DIR__;
$exception = new Exception();
$expected['file'] = F::filename(__FILE__);
$expected['line'] = $exception->getLine();
- $this->assertEquals($expected, $exception->toArray());
+ $this->assertSame($expected, $exception->toArray());
}
}
diff --git a/tests/Exception/InvalidArgumentExceptionTest.php b/tests/Exception/InvalidArgumentExceptionTest.php
index 129440ce47..393cd016ac 100644
--- a/tests/Exception/InvalidArgumentExceptionTest.php
+++ b/tests/Exception/InvalidArgumentExceptionTest.php
@@ -12,10 +12,10 @@ class InvalidArgumentExceptionTest extends TestCase
public function testDefaults()
{
$exception = new InvalidArgumentException();
- $this->assertEquals('error.invalidArgument', $exception->getKey());
- $this->assertEquals('Invalid argument "-" in method "-"', $exception->getMessage());
- $this->assertEquals(400, $exception->getHttpCode());
- $this->assertEquals(['argument' => null, 'method' => null], $exception->getData());
+ $this->assertSame('error.invalidArgument', $exception->getKey());
+ $this->assertSame('Invalid argument "-" in method "-"', $exception->getMessage());
+ $this->assertSame(400, $exception->getHttpCode());
+ $this->assertSame(['argument' => null, 'method' => null], $exception->getData());
}
/**
@@ -29,8 +29,8 @@ public function testPlaceholders()
'method' => 'get'
]
]);
- $this->assertEquals('Invalid argument "key" in method "get"', $exception->getMessage());
- $this->assertEquals([
+ $this->assertSame('Invalid argument "key" in method "get"', $exception->getMessage());
+ $this->assertSame([
'argument' => 'key',
'method' => 'get'
], $exception->getData());
diff --git a/tests/Exception/LogicExceptionTest.php b/tests/Exception/LogicExceptionTest.php
index 3ab982153f..814747fb48 100644
--- a/tests/Exception/LogicExceptionTest.php
+++ b/tests/Exception/LogicExceptionTest.php
@@ -12,8 +12,8 @@ class LogicExceptionTest extends TestCase
public function testDefaults()
{
$exception = new LogicException();
- $this->assertEquals('error.logic', $exception->getKey());
- $this->assertEquals('This task cannot be finished', $exception->getMessage());
- $this->assertEquals(400, $exception->getHttpCode());
+ $this->assertSame('error.logic', $exception->getKey());
+ $this->assertSame('This task cannot be finished', $exception->getMessage());
+ $this->assertSame(400, $exception->getHttpCode());
}
}
diff --git a/tests/Exception/NotFoundExceptionTest.php b/tests/Exception/NotFoundExceptionTest.php
index f076df6b28..5a31eedbef 100644
--- a/tests/Exception/NotFoundExceptionTest.php
+++ b/tests/Exception/NotFoundExceptionTest.php
@@ -12,8 +12,8 @@ class NotFoundExceptionTest extends TestCase
public function testDefaults()
{
$exception = new NotFoundException();
- $this->assertEquals('error.notFound', $exception->getKey());
- $this->assertEquals('Not found', $exception->getMessage());
- $this->assertEquals(404, $exception->getHttpCode());
+ $this->assertSame('error.notFound', $exception->getKey());
+ $this->assertSame('Not found', $exception->getMessage());
+ $this->assertSame(404, $exception->getHttpCode());
}
}
diff --git a/tests/Exception/PermissionExceptionTest.php b/tests/Exception/PermissionExceptionTest.php
index 09143da9ac..ef5fe90382 100644
--- a/tests/Exception/PermissionExceptionTest.php
+++ b/tests/Exception/PermissionExceptionTest.php
@@ -12,8 +12,8 @@ class PermissionExceptionTest extends TestCase
public function testDefaults()
{
$exception = new PermissionException();
- $this->assertEquals('error.permission', $exception->getKey());
- $this->assertEquals('You are not allowed to do this', $exception->getMessage());
- $this->assertEquals(403, $exception->getHttpCode());
+ $this->assertSame('error.permission', $exception->getKey());
+ $this->assertSame('You are not allowed to do this', $exception->getMessage());
+ $this->assertSame(403, $exception->getHttpCode());
}
}
diff --git a/tests/Form/FieldTest.php b/tests/Form/FieldTest.php
index 6aa03df28b..871d12a4c9 100644
--- a/tests/Form/FieldTest.php
+++ b/tests/Form/FieldTest.php
@@ -262,8 +262,8 @@ public function testHelp()
'help' => 'test'
]);
- $this->assertEquals('test', $field->help());
- $this->assertEquals('test', $field->help);
+ $this->assertEquals('test
', $field->help());
+ $this->assertEquals('test
', $field->help);
// translated
$field = new Field('test', [
@@ -274,8 +274,8 @@ public function testHelp()
]
]);
- $this->assertEquals('en', $field->help());
- $this->assertEquals('en', $field->help);
+ $this->assertEquals('en
', $field->help());
+ $this->assertEquals('en
', $field->help);
}
public function testIcon()
diff --git a/tests/Form/Fields/Mixins/FilePickerMixinTest.php b/tests/Form/Fields/Mixins/FilePickerMixinTest.php
index 7f7397ce7a..924bd391d3 100644
--- a/tests/Form/Fields/Mixins/FilePickerMixinTest.php
+++ b/tests/Form/Fields/Mixins/FilePickerMixinTest.php
@@ -16,7 +16,7 @@ public function testPageFiles()
'mixins' => ['filepicker'],
'methods' => [
'files' => function () {
- return $this->filepicker();
+ return $this->filepicker()['data'];
}
]
]
@@ -50,7 +50,7 @@ public function testFileFiles()
'mixins' => ['filepicker'],
'methods' => [
'files' => function () {
- return $this->filepicker();
+ return $this->filepicker()['data'];
}
]
]
@@ -84,7 +84,7 @@ public function testUserFiles()
'mixins' => ['filepicker'],
'methods' => [
'files' => function () {
- return $this->filepicker();
+ return $this->filepicker()['data'];
}
]
]
@@ -118,7 +118,7 @@ public function testSiteFiles()
'mixins' => ['filepicker'],
'methods' => [
'files' => function () {
- return $this->filepicker();
+ return $this->filepicker()['data'];
}
]
]
@@ -158,7 +158,7 @@ public function testCustomQuery()
'files' => function () {
return $this->filepicker([
'query' => $this->query
- ]);
+ ])['data'];
}
]
]
@@ -204,7 +204,7 @@ public function testMap()
'map' => function ($file) {
return $file->id();
}
- ]);
+ ])['data'];
}
]
]
diff --git a/tests/Form/Fields/Mixins/PagePickerMixinTest.php b/tests/Form/Fields/Mixins/PagePickerMixinTest.php
index cc9ee8f33c..7a648dcf07 100644
--- a/tests/Form/Fields/Mixins/PagePickerMixinTest.php
+++ b/tests/Form/Fields/Mixins/PagePickerMixinTest.php
@@ -53,7 +53,7 @@ public function testPagesWithoutParent()
]);
$response = $field->pages();
- $pages = $response['pages'];
+ $pages = $response['data'];
$model = $response['model'];
$this->assertEquals('Test', $model['title']);
@@ -106,7 +106,7 @@ public function testPagesWithParent()
]);
$response = $field->pages();
- $pages = $response['pages'];
+ $pages = $response['data'];
$model = $response['model'];
$this->assertEquals('a', $model['title']);
@@ -135,7 +135,65 @@ public function testPageChildren()
$page = new Page([
'slug' => 'test',
'children' => [
- ['slug' => 'a'],
+ [
+ 'slug' => 'a',
+ 'children' => [
+ ['slug' => 'aa'],
+ ['slug' => 'ab'],
+ ['slug' => 'ac'],
+ ]
+ ],
+ ['slug' => 'b'],
+ ['slug' => 'c'],
+ ]
+ ]);
+
+ $field = $this->field('test', [
+ 'model' => $page
+ ]);
+
+ $response = $field->pages();
+ $pages = $response['data'];
+ $model = $response['model'];
+
+ $this->assertCount(3, $model);
+ $this->assertNull($model['id']);
+ $this->assertNull($model['parent']);
+ $this->assertSame('test', $model['title']);
+
+ $this->assertCount(3, $pages);
+ $this->assertSame('test/a', $pages[0]['id']);
+ $this->assertSame('test/b', $pages[1]['id']);
+ $this->assertSame('test/c', $pages[2]['id']);
+ }
+
+ public function testPageChildrenWithoutSubpages()
+ {
+ Field::$types = [
+ 'test' => [
+ 'mixins' => ['pagepicker'],
+ 'methods' => [
+ 'pages' => function () {
+ return $this->pagepicker([
+ 'query' => 'page.children',
+ 'subpages' => false
+ ]);
+ }
+ ]
+ ]
+ ];
+
+ $page = new Page([
+ 'slug' => 'test',
+ 'children' => [
+ [
+ 'slug' => 'a',
+ 'children' => [
+ ['slug' => 'aa'],
+ ['slug' => 'ab'],
+ ['slug' => 'ac'],
+ ]
+ ],
['slug' => 'b'],
['slug' => 'c'],
]
@@ -146,9 +204,10 @@ public function testPageChildren()
]);
$response = $field->pages();
- $pages = $response['pages'];
+ $pages = $response['data'];
+ $model = $response['model'];
- $this->assertNull($response['model']);
+ $this->assertNull($model);
$this->assertCount(3, $pages);
$this->assertEquals('test/a', $pages[0]['id']);
$this->assertEquals('test/b', $pages[1]['id']);
@@ -187,7 +246,7 @@ public function testMap()
]);
$response = $field->pages();
- $pages = $response['pages'];
+ $pages = $response['data'];
$this->assertEquals(['test/a', 'test/b', 'test/c'], $pages);
}
diff --git a/tests/Form/Fields/Mixins/UserPickerMixinTest.php b/tests/Form/Fields/Mixins/UserPickerMixinTest.php
index e9e0070948..b282c6306f 100644
--- a/tests/Form/Fields/Mixins/UserPickerMixinTest.php
+++ b/tests/Form/Fields/Mixins/UserPickerMixinTest.php
@@ -33,7 +33,7 @@ public function testUsersWithoutQuery()
'mixins' => ['userpicker'],
'methods' => [
'users' => function () {
- return $this->userpicker();
+ return $this->userpicker()['data'];
}
]
]
@@ -64,7 +64,7 @@ public function testUsersWithQuery()
'users' => function () {
return $this->userpicker([
'query' => 'kirby.users.role("editor")'
- ]);
+ ])['data'];
}
]
]
@@ -96,7 +96,7 @@ public function testMap()
'map' => function ($user) {
return $user->email();
}
- ]);
+ ])['data'];
}
]
]
diff --git a/tests/Form/Fields/StructureFieldTest.php b/tests/Form/Fields/StructureFieldTest.php
index 2496bb8294..90c05aaaa0 100644
--- a/tests/Form/Fields/StructureFieldTest.php
+++ b/tests/Form/Fields/StructureFieldTest.php
@@ -10,13 +10,17 @@ class StructureFieldTest extends TestCase
public function testDefaultProps()
{
$field = $this->field('structure', [
- 'fields' => []
+ 'fields' => [
+ 'text' => [
+ 'type' => 'text'
+ ]
+ ]
]);
$this->assertEquals('structure', $field->type());
$this->assertEquals('structure', $field->name());
$this->assertEquals(null, $field->limit());
- $this->assertEquals([], $field->fields());
+ $this->assertTrue(is_array($field->fields()));
$this->assertEquals([], $field->value());
$this->assertTrue($field->save());
}
@@ -216,7 +220,11 @@ public function testFloatsWithNonUsLocale()
public function testEmpty()
{
$field = $this->field('structure', [
- 'fields' => [],
+ 'fields' => [
+ 'text' => [
+ 'type' => 'text'
+ ]
+ ],
'empty' => 'Test'
]);
@@ -226,7 +234,11 @@ public function testEmpty()
public function testTranslatedEmpty()
{
$field = $this->field('structure', [
- 'fields' => [],
+ 'fields' => [
+ 'text' => [
+ 'type' => 'text'
+ ]
+ ],
'empty' => ['en' => 'Test', 'de' => 'Töst']
]);
diff --git a/tests/Form/OptionsApiTest.php b/tests/Form/OptionsApiTest.php
index 5b4db2ffce..4991a4d242 100644
--- a/tests/Form/OptionsApiTest.php
+++ b/tests/Form/OptionsApiTest.php
@@ -9,6 +9,9 @@
class OptionsApiTest extends TestCase
{
+ protected $app;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Form/OptionsTest.php b/tests/Form/OptionsTest.php
index a738d5b797..7b6cd119d1 100644
--- a/tests/Form/OptionsTest.php
+++ b/tests/Form/OptionsTest.php
@@ -10,6 +10,9 @@
class OptionsTest extends TestCase
{
+ protected $app;
+ protected $fixtures;
+
public function setUp(): void
{
$this->app = new App([
diff --git a/tests/Http/RemoteTest.php b/tests/Http/RemoteTest.php
index 3239254cda..62f21280a3 100644
--- a/tests/Http/RemoteTest.php
+++ b/tests/Http/RemoteTest.php
@@ -6,6 +6,8 @@
class RemoteTest extends TestCase
{
+ protected $defaults;
+
public function setUp(): void
{
$this->defaults = Remote::$defaults;
diff --git a/tests/Http/ResponseTest.php b/tests/Http/ResponseTest.php
index 27343a495e..f4ba658ebf 100644
--- a/tests/Http/ResponseTest.php
+++ b/tests/Http/ResponseTest.php
@@ -185,6 +185,7 @@ public function testRedirectWithResponseCode()
/**
* @runInSeparateProcess
+ * @preserveGlobalState disabled
*/
public function testSend()
{
@@ -210,6 +211,7 @@ public function testSend()
/**
* @runInSeparateProcess
+ * @preserveGlobalState disabled
*/
public function testToString()
{
diff --git a/tests/Http/RouterTest.php b/tests/Http/RouterTest.php
index 5f1cdca690..fd335f5b38 100644
--- a/tests/Http/RouterTest.php
+++ b/tests/Http/RouterTest.php
@@ -148,6 +148,7 @@ public function testNext()
return 'a';
}
+ /** @var \Kirby\Http\Route $this */
$this->next();
}
],
@@ -158,6 +159,7 @@ public function testNext()
return 'b';
}
+ /** @var \Kirby\Http\Route $this */
$this->next();
}
],
@@ -168,6 +170,7 @@ public function testNext()
return 'c';
}
+ /** @var \Kirby\Http\Route $this */
$this->next();
}
]
diff --git a/tests/Http/UriTest.php b/tests/Http/UriTest.php
index d037671ba9..dff18cacc2 100644
--- a/tests/Http/UriTest.php
+++ b/tests/Http/UriTest.php
@@ -7,6 +7,8 @@
class UriTest extends TestCase
{
protected $_SERVER = null;
+ protected $example1;
+ protected $example2;
protected function setUp(): void
{
diff --git a/tests/Http/VisitorTest.php b/tests/Http/VisitorTest.php
index 7ff1a65068..734352a982 100644
--- a/tests/Http/VisitorTest.php
+++ b/tests/Http/VisitorTest.php
@@ -50,13 +50,54 @@ public function testUserAgent()
$this->assertEquals('Kirby', $visitor->userAgent());
}
- public function testAccepts()
+ public function testAcceptsMimeType()
{
$visitor = new Visitor();
$this->assertFalse($visitor->acceptsMimeType('text/html'));
$visitor = new Visitor(['acceptedMimeType' => 'text/html']);
$this->assertTrue($visitor->acceptsMimeType('text/html'));
+ $this->assertFalse($visitor->acceptsMimeType('application/json'));
+ }
+
+ public function testPreferredMimeType()
+ {
+ $visitor = new Visitor(['acceptedMimeType' => 'text/html;q=0.8,application/json,text/plain;q=0.9,text/*;q=0.7']);
+
+ $this->assertSame('text/html', $visitor->preferredMimeType('text/html'));
+ $this->assertSame('text/plain', $visitor->preferredMimeType('text/plain'));
+ $this->assertSame('application/json', $visitor->preferredMimeType('application/json'));
+ $this->assertSame('text/xml', $visitor->preferredMimeType('text/xml'));
+ $this->assertNull($visitor->preferredMimeType('application/yaml'));
+
+ $this->assertSame('text/plain', $visitor->preferredMimeType('text/html', 'text/plain'));
+ $this->assertSame('text/plain', $visitor->preferredMimeType('text/plain', 'text/xml'));
+ $this->assertSame('application/json', $visitor->preferredMimeType('text/html', 'application/json'));
+ $this->assertSame('application/json', $visitor->preferredMimeType('text/plain', 'application/json'));
+ $this->assertSame('application/json', $visitor->preferredMimeType('text/xml', 'application/json'));
+
+ $this->assertSame('application/json', $visitor->preferredMimeType('text/html', 'text/plain', 'application/json'));
+ $this->assertSame('application/json', $visitor->preferredMimeType('text/html', 'text/plain', 'application/json', 'text/xml'));
+
+ $this->assertSame('application/json', $visitor->preferredMimeType('application/yaml', 'application/json'));
+ }
+
+ public function testPrefersJson()
+ {
+ $visitor = new Visitor(['acceptedMimeType' => 'text/html;q=0.8,application/json']);
+ $this->assertTrue($visitor->prefersJson());
+
+ $visitor = new Visitor(['acceptedMimeType' => 'application/json']);
+ $this->assertTrue($visitor->prefersJson());
+
+ $visitor = new Visitor(['acceptedMimeType' => 'text/html,application/json;q=0.8']);
+ $this->assertFalse($visitor->prefersJson());
+
+ $visitor = new Visitor(['acceptedMimeType' => 'text/html']);
+ $this->assertFalse($visitor->prefersJson());
+
+ $visitor = new Visitor(['acceptedMimeType' => 'text/xml']);
+ $this->assertFalse($visitor->prefersJson());
}
public function testAcceptsLanguage()
diff --git a/tests/Session/AutoSessionTest.php b/tests/Session/AutoSessionTest.php
index 25c75bd6e5..95cfec2514 100644
--- a/tests/Session/AutoSessionTest.php
+++ b/tests/Session/AutoSessionTest.php
@@ -41,19 +41,19 @@ public function testSessionsOptions()
// store object as store
$autoSession = new AutoSession($this->store);
- $this->assertEquals($this->store, $sessionsProperty->getValue($autoSession)->store());
+ $this->assertSame($this->store, $sessionsProperty->getValue($autoSession)->store());
// path string as store
$autoSession = new AutoSession(__DIR__ . '/fixtures/store');
- $this->assertEquals(__DIR__ . '/fixtures/store', $pathProperty->getValue($sessionsProperty->getValue($autoSession)->store()));
+ $this->assertSame(__DIR__ . '/fixtures/store', $pathProperty->getValue($sessionsProperty->getValue($autoSession)->store()));
// default cookie name
$autoSession = new AutoSession($this->store);
- $this->assertEquals('kirby_session', $sessionsProperty->getValue($autoSession)->cookieName());
+ $this->assertSame('kirby_session', $sessionsProperty->getValue($autoSession)->cookieName());
// custom cookie name
$autoSession = new AutoSession($this->store, ['cookieName' => 'my_cookie']);
- $this->assertEquals('my_cookie', $sessionsProperty->getValue($autoSession)->cookieName());
+ $this->assertSame('my_cookie', $sessionsProperty->getValue($autoSession)->cookieName());
// collect garbage every time
$this->store->collectedGarbage = false;
@@ -77,22 +77,22 @@ public function testGet()
// default: no detection
$session = $autoSession->get();
- $this->assertEquals('9999999999.valid.' . $this->store->validKey, $session->token());
+ $this->assertSame('9999999999.valid.' . $this->store->validKey, $session->token());
// use detection
$session = $autoSession->get(['detect' => true]);
- $this->assertEquals('9999999999.valid2.' . $this->store->validKey, $session->token());
+ $this->assertSame('9999999999.valid2.' . $this->store->validKey, $session->token());
// newly created session
Cookie::remove('kirby_session');
unset($_SERVER['HTTP_AUTHORIZATION']);
$session = $autoSession->get();
$this->assertNull($session->token());
- $this->assertEquals('cookie', $session->mode());
- $this->assertEquals(1337000000, $session->startTime()); // timestamp is from mock
- $this->assertEquals(7200, $session->duration());
- $this->assertEquals(1337000000 + 7200, $session->expiryTime()); // timestamp is from mock
- $this->assertEquals(1800, $session->timeout());
+ $this->assertSame('cookie', $session->mode());
+ $this->assertSame(1337000000, $session->startTime()); // timestamp is from mock
+ $this->assertSame(7200, $session->duration());
+ $this->assertSame(1337000000 + 7200, $session->expiryTime()); // timestamp is from mock
+ $this->assertSame(1800, $session->timeout());
$this->assertTrue($session->renewable());
// session needs to be the same one each time
@@ -102,56 +102,56 @@ public function testGet()
$autoSession = new AutoSession($this->store);
$session = $autoSession->get(['createMode' => 'manual']);
$this->assertNull($session->token());
- $this->assertEquals('manual', $session->mode());
+ $this->assertSame('manual', $session->mode());
// getting a session with the default createMode shouldn't change the mode
$session = $autoSession->get();
$this->assertNull($session->token());
- $this->assertEquals('manual', $session->mode());
+ $this->assertSame('manual', $session->mode());
// but in the other direction it should
$autoSession = new AutoSession($this->store);
$session = $autoSession->get();
$this->assertNull($session->token());
- $this->assertEquals('cookie', $session->mode());
+ $this->assertSame('cookie', $session->mode());
$session = $autoSession->get(['createMode' => 'manual']);
$this->assertNull($session->token());
- $this->assertEquals('manual', $session->mode());
+ $this->assertSame('manual', $session->mode());
// but not if the session has already been initialized
$autoSession = new AutoSession($this->store);
$session = $autoSession->get();
$this->assertNull($session->token());
- $this->assertEquals('cookie', $session->mode());
+ $this->assertSame('cookie', $session->mode());
$session->data()->set('someKey', 'someValue');
$this->assertNotNull($session->token());
$session = $autoSession->get(['createMode' => 'manual']);
$this->assertNotNull($session->token());
- $this->assertEquals('cookie', $session->mode());
+ $this->assertSame('cookie', $session->mode());
// long session defaults
$autoSession = new AutoSession($this->store);
$session = $autoSession->get(['long' => true]);
$this->assertNull($session->token());
- $this->assertEquals('cookie', $session->mode());
- $this->assertEquals(1337000000, $session->startTime()); // timestamp is from mock
- $this->assertEquals(1209600, $session->duration());
- $this->assertEquals(1337000000 + 1209600, $session->expiryTime()); // timestamp is from mock
+ $this->assertSame('cookie', $session->mode());
+ $this->assertSame(1337000000, $session->startTime()); // timestamp is from mock
+ $this->assertSame(1209600, $session->duration());
+ $this->assertSame(1337000000 + 1209600, $session->expiryTime()); // timestamp is from mock
$this->assertFalse($session->timeout());
$this->assertTrue($session->renewable());
// session config update when switching to long session
$autoSession = new AutoSession($this->store);
$session = $autoSession->get();
- $this->assertEquals(7200, $session->duration());
- $this->assertEquals(1800, $session->timeout());
+ $this->assertSame(7200, $session->duration());
+ $this->assertSame(1800, $session->timeout());
$session->data()->set('id', 'awesome session');
$session->commit();
Cookie::set('kirby_session', $session->token());
$session = $autoSession->get(['long' => true]);
- $this->assertEquals('awesome session', $session->data()->get('id'));
- $this->assertEquals(1209600, $session->duration());
- $this->assertEquals(false, $session->timeout());
+ $this->assertSame('awesome session', $session->data()->get('id'));
+ $this->assertSame(1209600, $session->duration());
+ $this->assertSame(false, $session->timeout());
Cookie::remove('kirby_session');
// custom duration and timeout (normal session)
@@ -162,28 +162,28 @@ public function testGet()
]);
$session = $autoSession->get();
$this->assertNull($session->token());
- $this->assertEquals('cookie', $session->mode());
- $this->assertEquals(1337000000, $session->startTime()); // timestamp is from mock
- $this->assertEquals(1, $session->duration());
- $this->assertEquals(1337000000 + 1, $session->expiryTime()); // timestamp is from mock
- $this->assertEquals(1234, $session->timeout());
+ $this->assertSame('cookie', $session->mode());
+ $this->assertSame(1337000000, $session->startTime()); // timestamp is from mock
+ $this->assertSame(1, $session->duration());
+ $this->assertSame(1337000000 + 1, $session->expiryTime()); // timestamp is from mock
+ $this->assertSame(1234, $session->timeout());
$this->assertTrue($session->renewable());
// custom duration and timeout (long session)
$session = $autoSession->get(['long' => true]);
$this->assertNull($session->token());
- $this->assertEquals('cookie', $session->mode());
- $this->assertEquals(1337000000, $session->startTime()); // timestamp is from mock
- $this->assertEquals(5, $session->duration());
- $this->assertEquals(1337000000 + 5, $session->expiryTime()); // timestamp is from mock
+ $this->assertSame('cookie', $session->mode());
+ $this->assertSame(1337000000, $session->startTime()); // timestamp is from mock
+ $this->assertSame(5, $session->duration());
+ $this->assertSame(1337000000 + 5, $session->expiryTime()); // timestamp is from mock
$this->assertFalse($session->timeout());
$this->assertTrue($session->renewable());
// session config update when the configuration changed
$autoSession = new AutoSession($this->store);
$session = $autoSession->get();
- $this->assertEquals(7200, $session->duration());
- $this->assertEquals(1800, $session->timeout());
+ $this->assertSame(7200, $session->duration());
+ $this->assertSame(1800, $session->timeout());
$session->data()->set('id', 'awesome session');
$session->commit();
Cookie::set('kirby_session', $session->token());
@@ -191,39 +191,39 @@ public function testGet()
// lower values: shouldn't change anything
$autoSession = new AutoSession($this->store, ['durationNormal' => 7100, 'timeout' => 1000]);
$session = $autoSession->get();
- $this->assertEquals('awesome session', $session->data()->get('id'));
- $this->assertEquals(7200, $session->duration());
- $this->assertEquals(1800, $session->timeout());
+ $this->assertSame('awesome session', $session->data()->get('id'));
+ $this->assertSame(7200, $session->duration());
+ $this->assertSame(1800, $session->timeout());
$session->commit();
// higher values: should update
$autoSession = new AutoSession($this->store, ['durationNormal' => 7300, 'timeout' => 1900]);
$session = $autoSession->get();
- $this->assertEquals('awesome session', $session->data()->get('id'));
- $this->assertEquals(7300, $session->duration());
- $this->assertEquals(1900, $session->timeout());
+ $this->assertSame('awesome session', $session->data()->get('id'));
+ $this->assertSame(7300, $session->duration());
+ $this->assertSame(1900, $session->timeout());
$session->commit();
// remove timeout: should update
$autoSession = new AutoSession($this->store, ['timeout' => false]);
$session = $autoSession->get();
- $this->assertEquals('awesome session', $session->data()->get('id'));
- $this->assertEquals(7300, $session->duration());
- $this->assertEquals(false, $session->timeout());
+ $this->assertSame('awesome session', $session->data()->get('id'));
+ $this->assertSame(7300, $session->duration());
+ $this->assertSame(false, $session->timeout());
Cookie::remove('kirby_session');
// timeout for the first time: shouldn't change anything
$autoSession = new AutoSession($this->store);
$session = $autoSession->get(['long' => true]);
- $this->assertEquals(1209600, $session->duration());
- $this->assertEquals(false, $session->timeout());
+ $this->assertSame(1209600, $session->duration());
+ $this->assertSame(false, $session->timeout());
$session->data()->set('id', 'awesome session');
$session->commit();
Cookie::set('kirby_session', $session->token());
$session = $autoSession->get();
- $this->assertEquals('awesome session', $session->data()->get('id'));
- $this->assertEquals(1209600, $session->duration());
- $this->assertEquals(false, $session->timeout());
+ $this->assertSame('awesome session', $session->data()->get('id'));
+ $this->assertSame(1209600, $session->duration());
+ $this->assertSame(false, $session->timeout());
$session->commit();
}
@@ -236,8 +236,8 @@ public function testCreateManually()
$session = $autoSession->createManually(['expiryTime' => 9999999999, 'mode' => 'cookie']);
$this->assertNull($session->token());
- $this->assertEquals(9999999999, $session->expiryTime());
- $this->assertEquals('manual', $session->mode());
+ $this->assertSame(9999999999, $session->expiryTime());
+ $this->assertSame('manual', $session->mode());
}
/**
diff --git a/tests/Session/FileSessionStoreTest.php b/tests/Session/FileSessionStoreTest.php
index 1b36e0fe83..df7292614e 100644
--- a/tests/Session/FileSessionStoreTest.php
+++ b/tests/Session/FileSessionStoreTest.php
@@ -75,7 +75,7 @@ public function testCreateId()
$id = $this->store->createId(1234567890);
$this->assertStringMatchesFormat('%x', $id);
- $this->assertEquals(20, strlen($id));
+ $this->assertSame(20, strlen($id));
$this->assertFileExists($this->root . '/1234567890.' . $id . '.sess');
$this->assertHandleExists('1234567890.' . $id);
$this->assertLocked('1234567890.' . $id);
@@ -169,10 +169,10 @@ public function testUnlock()
*/
public function testGet()
{
- $this->assertEquals('1234567890', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
+ $this->assertSame('1234567890', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
$this->assertHandleExists('1234567890.abcdefghijabcdefghij');
- $this->assertEquals('', $this->store->get(8888888888, 'abcdefghijabcdefghij'));
+ $this->assertSame('', $this->store->get(8888888888, 'abcdefghijabcdefghij'));
}
/**
@@ -211,15 +211,15 @@ public function testGetUnreadableFile()
*/
public function testSet()
{
- $this->assertEquals('1234567890', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
+ $this->assertSame('1234567890', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
$this->store->lock(1234567890, 'abcdefghijabcdefghij');
$this->store->set(1234567890, 'abcdefghijabcdefghij', 'some other data');
$this->assertLocked('1234567890.abcdefghijabcdefghij');
$this->assertHandleExists('1234567890.abcdefghijabcdefghij');
- $this->assertEquals('some other data', F::read($this->root . '/1234567890.abcdefghijabcdefghij.sess'));
- $this->assertEquals('some other data', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
+ $this->assertSame('some other data', F::read($this->root . '/1234567890.abcdefghijabcdefghij.sess'));
+ $this->assertSame('some other data', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
}
/**
@@ -245,7 +245,7 @@ public function testSetWithoutLock()
$this->expectException('Kirby\Exception\LogicException');
$this->expectExceptionCode('error.session.filestore.notLocked');
- $this->assertEquals('1234567890', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
+ $this->assertSame('1234567890', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
$this->store->set(1234567890, 'abcdefghijabcdefghij', 'some other data');
}
@@ -278,7 +278,7 @@ public function testDestroy()
public function testDestroyAlreadyDestroyed()
{
// make sure we get a handle
- $this->assertEquals('1234567890', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
+ $this->assertSame('1234567890', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
$this->assertHandleExists('1234567890.abcdefghijabcdefghij');
// simulate that another thread deleted the file
@@ -299,7 +299,7 @@ public function testAccessAfterDestroy()
$this->expectExceptionCode('error.session.filestore.notFound');
// make sure we get a handle
- $this->assertEquals('1234567890', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
+ $this->assertSame('1234567890', $this->store->get(1234567890, 'abcdefghijabcdefghij'));
$this->store->lock(1234567890, 'abcdefghijabcdefghij');
$this->assertHandleExists('1234567890.abcdefghijabcdefghij');
@@ -335,7 +335,7 @@ public function testCollectGarbage()
/**
* Asserts that the given session is currently locked
*
- * @param string $name Combined name
+ * @param string $name Combined name
* @return void
*/
protected function assertLocked(string $name)
@@ -356,7 +356,7 @@ protected function assertLocked(string $name)
/**
* Asserts that the given session is currently not locked
*
- * @param string $name Combined name
+ * @param string $name Combined name
* @return void
*/
protected function assertNotLocked(string $name)
@@ -377,7 +377,7 @@ protected function assertNotLocked(string $name)
/**
* Asserts that the given session currently has an open handle
*
- * @param string $name Combined name
+ * @param string $name Combined name
* @return void
*/
protected function assertHandleExists(string $name)
@@ -389,7 +389,7 @@ protected function assertHandleExists(string $name)
/**
* Asserts that the given session currently has no open handle
*
- * @param string $name Combined name
+ * @param string $name Combined name
* @return void
*/
protected function assertHandleNotExists(string $name)
diff --git a/tests/Session/SessionDataTest.php b/tests/Session/SessionDataTest.php
index 7806358484..93ca110228 100644
--- a/tests/Session/SessionDataTest.php
+++ b/tests/Session/SessionDataTest.php
@@ -39,7 +39,7 @@ public function testSet()
$this->sessionData->set('someKey', 'someValue');
$this->assertTrue($this->session->ensuredToken);
$this->assertTrue($this->session->preparedForWriting);
- $this->assertEquals('someValue', $this->sessionData->get('someKey'));
+ $this->assertSame('someValue', $this->sessionData->get('someKey'));
// key-value array
$this->session->ensuredToken = false;
@@ -50,8 +50,8 @@ public function testSet()
]);
$this->assertTrue($this->session->ensuredToken);
$this->assertTrue($this->session->preparedForWriting);
- $this->assertEquals('someValue1', $this->sessionData->get('someKey1'));
- $this->assertEquals('someValue2', $this->sessionData->get('someKey2'));
+ $this->assertSame('someValue1', $this->sessionData->get('someKey1'));
+ $this->assertSame('someValue2', $this->sessionData->get('someKey2'));
}
/**
@@ -71,25 +71,25 @@ public function testIncrement()
{
$this->session->ensuredToken = false;
$this->session->preparedForWriting = false;
- $this->assertEquals(123, $this->sessionData->get('someInt'));
+ $this->assertSame(123, $this->sessionData->get('someInt'));
$this->sessionData->increment('someInt', 10);
$this->assertTrue($this->session->ensuredToken);
$this->assertTrue($this->session->preparedForWriting);
- $this->assertEquals(133, $this->sessionData->get('someInt'));
+ $this->assertSame(133, $this->sessionData->get('someInt'));
$this->sessionData->increment('someInt', 10, 120);
- $this->assertEquals(133, $this->sessionData->get('someInt'));
+ $this->assertSame(133, $this->sessionData->get('someInt'));
$this->sessionData->increment('someInt', 10, 140);
- $this->assertEquals(140, $this->sessionData->get('someInt'));
+ $this->assertSame(140, $this->sessionData->get('someInt'));
$this->sessionData->increment(['someInt', 'someNewInt'], 10, 145);
- $this->assertEquals(145, $this->sessionData->get('someInt'));
- $this->assertEquals(10, $this->sessionData->get('someNewInt'));
+ $this->assertSame(145, $this->sessionData->get('someInt'));
+ $this->assertSame(10, $this->sessionData->get('someNewInt'));
$this->sessionData->increment('someInt', 10, 200);
- $this->assertEquals(155, $this->sessionData->get('someInt'));
+ $this->assertSame(155, $this->sessionData->get('someInt'));
}
/**
@@ -130,25 +130,25 @@ public function testDecrement()
{
$this->session->ensuredToken = false;
$this->session->preparedForWriting = false;
- $this->assertEquals(123, $this->sessionData->get('someInt'));
+ $this->assertSame(123, $this->sessionData->get('someInt'));
$this->sessionData->decrement('someInt', 10);
$this->assertTrue($this->session->ensuredToken);
$this->assertTrue($this->session->preparedForWriting);
- $this->assertEquals(113, $this->sessionData->get('someInt'));
+ $this->assertSame(113, $this->sessionData->get('someInt'));
$this->sessionData->decrement('someInt', 10, 150);
- $this->assertEquals(113, $this->sessionData->get('someInt'));
+ $this->assertSame(113, $this->sessionData->get('someInt'));
$this->sessionData->decrement('someInt', 10, 105);
- $this->assertEquals(105, $this->sessionData->get('someInt'));
+ $this->assertSame(105, $this->sessionData->get('someInt'));
$this->sessionData->decrement(['someInt', 'someNewInt'], 10, -5);
- $this->assertEquals(95, $this->sessionData->get('someInt'));
- $this->assertEquals(-5, $this->sessionData->get('someNewInt'));
+ $this->assertSame(95, $this->sessionData->get('someInt'));
+ $this->assertSame(-5, $this->sessionData->get('someNewInt'));
$this->sessionData->decrement('someInt', 10, 50);
- $this->assertEquals(85, $this->sessionData->get('someInt'));
+ $this->assertSame(85, $this->sessionData->get('someInt'));
}
/**
@@ -188,13 +188,13 @@ public function testDecrementNonIntValue()
public function testGet()
{
// string as key
- $this->assertEquals('someValue', $this->sessionData->get('someString', 'someDefault'));
- $this->assertEquals(null, $this->sessionData->get('someOtherString'));
- $this->assertEquals('someDefault', $this->sessionData->get('someOtherString', 'someDefault'));
- $this->assertEquals(123, $this->sessionData->get('someInt', 456));
+ $this->assertSame('someValue', $this->sessionData->get('someString', 'someDefault'));
+ $this->assertSame(null, $this->sessionData->get('someOtherString'));
+ $this->assertSame('someDefault', $this->sessionData->get('someOtherString', 'someDefault'));
+ $this->assertSame(123, $this->sessionData->get('someInt', 456));
// all data
- $this->assertEquals([
+ $this->assertSame([
'someString' => 'someValue',
'someInt' => 123
], $this->sessionData->get());
@@ -217,13 +217,13 @@ public function testPull()
{
$this->session->ensuredToken = false;
$this->session->preparedForWriting = false;
- $this->assertEquals('someValue', $this->sessionData->pull('someString'));
+ $this->assertSame('someValue', $this->sessionData->pull('someString'));
$this->assertFalse($this->session->ensuredToken);
$this->assertTrue($this->session->preparedForWriting);
- $this->assertEquals(null, $this->sessionData->get('someString'));
+ $this->assertSame(null, $this->sessionData->get('someString'));
- $this->assertEquals(null, $this->sessionData->pull('someOtherString'));
- $this->assertEquals('someDefault', $this->sessionData->pull('someOtherString', 'someDefault'));
+ $this->assertSame(null, $this->sessionData->pull('someOtherString'));
+ $this->assertSame('someDefault', $this->sessionData->pull('someOtherString', 'someDefault'));
}
/**
@@ -237,7 +237,7 @@ public function testRemove()
$this->sessionData->remove('someString');
$this->assertFalse($this->session->ensuredToken);
$this->assertTrue($this->session->preparedForWriting);
- $this->assertEquals(null, $this->sessionData->get('someString'));
+ $this->assertSame(null, $this->sessionData->get('someString'));
// key-value array
$this->session->ensuredToken = false;
@@ -245,7 +245,7 @@ public function testRemove()
$this->sessionData->remove(['someString', 'someInt', 'someOtherString']);
$this->assertFalse($this->session->ensuredToken);
$this->assertTrue($this->session->preparedForWriting);
- $this->assertEquals([], $this->sessionData->get());
+ $this->assertSame([], $this->sessionData->get());
}
/**
@@ -268,7 +268,7 @@ public function testClear()
$this->sessionData->clear();
$this->assertFalse($this->session->ensuredToken);
$this->assertTrue($this->session->preparedForWriting);
- $this->assertEquals([], $this->sessionData->get());
+ $this->assertSame([], $this->sessionData->get());
}
/**
@@ -283,6 +283,6 @@ public function testReload()
$this->sessionData->reload($newData);
$this->assertFalse($this->session->ensuredToken);
$this->assertFalse($this->session->preparedForWriting);
- $this->assertEquals($newData, $this->sessionData->get());
+ $this->assertSame($newData, $this->sessionData->get());
}
}
diff --git a/tests/Session/SessionStoreTest.php b/tests/Session/SessionStoreTest.php
index f5d4bede44..d228ef0453 100644
--- a/tests/Session/SessionStoreTest.php
+++ b/tests/Session/SessionStoreTest.php
@@ -22,11 +22,11 @@ public function testGenerateId()
$id1 = $generateId->invoke(null);
$this->assertStringMatchesFormat('%x', $id1);
- $this->assertEquals(20, strlen($id1));
+ $this->assertSame(20, strlen($id1));
$id2 = $generateId->invoke(null);
$this->assertStringMatchesFormat('%x', $id2);
- $this->assertEquals(20, strlen($id2));
- $this->assertNotEquals($id1, $id2);
+ $this->assertSame(20, strlen($id2));
+ $this->assertNotSame($id1, $id2);
}
}
diff --git a/tests/Session/SessionTest.php b/tests/Session/SessionTest.php
index b146b6207c..5c68375d29 100644
--- a/tests/Session/SessionTest.php
+++ b/tests/Session/SessionTest.php
@@ -57,13 +57,13 @@ public function testCreate()
// defaults
$session = new Session($this->sessions, null, []);
- $this->assertEquals(1337000000, $session->startTime()); // timestamp is from mock
- $this->assertEquals(1337000000 + 7200, $session->expiryTime()); // timestamp is from mock
- $this->assertEquals(7200, $session->duration());
- $this->assertEquals(1800, $session->timeout());
- $this->assertEquals(1337000000, $activityProperty->getValue($session)); // timestamp is from mock
- $this->assertEquals(true, $session->renewable());
- $this->assertEquals([], $session->data()->get());
+ $this->assertSame(1337000000, $session->startTime()); // timestamp is from mock
+ $this->assertSame(1337000000 + 7200, $session->expiryTime()); // timestamp is from mock
+ $this->assertSame(7200, $session->duration());
+ $this->assertSame(1800, $session->timeout());
+ $this->assertSame(1337000000, $activityProperty->getValue($session)); // timestamp is from mock
+ $this->assertSame(true, $session->renewable());
+ $this->assertSame([], $session->data()->get());
$this->assertNull($session->token());
$this->assertWriteMode(false, $session);
@@ -74,13 +74,13 @@ public function testCreate()
'timeout' => false,
'renewable' => false
]);
- $this->assertEquals(1337000000 + 60, $session->startTime()); // timestamp is from mock
- $this->assertEquals(1337000000 + 3660, $session->expiryTime()); // timestamp is from mock
- $this->assertEquals(3600, $session->duration());
+ $this->assertSame(1337000000 + 60, $session->startTime()); // timestamp is from mock
+ $this->assertSame(1337000000 + 3660, $session->expiryTime()); // timestamp is from mock
+ $this->assertSame(3600, $session->duration());
$this->assertFalse($session->timeout());
- $this->assertEquals(null, $activityProperty->getValue($session));
- $this->assertEquals(false, $session->renewable());
- $this->assertEquals([], $session->data()->get());
+ $this->assertSame(null, $activityProperty->getValue($session));
+ $this->assertSame(false, $session->renewable());
+ $this->assertSame([], $session->data()->get());
$this->assertNull($session->token());
$this->assertWriteMode(false, $session);
@@ -173,9 +173,9 @@ public function testMode()
'mode' => 'manual'
]);
- $this->assertEquals('manual', $session->mode());
- $this->assertEquals('cookie', $session->mode('cookie'));
- $this->assertEquals('cookie', $session->mode());
+ $this->assertSame('manual', $session->mode());
+ $this->assertSame('cookie', $session->mode('cookie'));
+ $this->assertSame('cookie', $session->mode());
}
/**
@@ -191,7 +191,7 @@ public function testModeStartedSession()
]);
$session->data()->set('someKey', 'someValue');
- $this->assertEquals('manual', $session->mode());
+ $this->assertSame('manual', $session->mode());
$session->mode('cookie');
}
@@ -212,19 +212,19 @@ public function testExpiryTime()
$session->commit();
$originalToken = $session->token();
- $this->assertEquals(7777777777, $session->expiryTime());
- $this->assertEquals(6777777777, $session->duration());
+ $this->assertSame(7777777777, $session->expiryTime());
+ $this->assertSame(6777777777, $session->duration());
$this->assertWriteMode(false, $session);
- $this->assertEquals(9999999999, $session->expiryTime(9999999999));
- $this->assertEquals(9999999999, $session->expiryTime());
+ $this->assertSame(9999999999, $session->expiryTime(9999999999));
+ $this->assertSame(9999999999, $session->expiryTime());
$this->assertWriteMode(true, $session);
- $this->assertNotEquals($originalToken, $session->token());
+ $this->assertNotSame($originalToken, $session->token());
$originalToken = $session->token();
- $this->assertEquals(1337000000 + 3600, $newExpiry = $session->expiryTime('+ 1 hour')); // timestamp is from mock
- $this->assertEquals($newExpiry, $session->expiryTime());
- $this->assertEquals(3600, $session->duration());
+ $this->assertSame(1337000000 + 3600, $newExpiry = $session->expiryTime('+ 1 hour')); // timestamp is from mock
+ $this->assertSame($newExpiry, $session->expiryTime());
+ $this->assertSame(3600, $session->duration());
$this->assertWriteMode(true, $session);
- $this->assertNotEquals($originalToken, $session->token());
+ $this->assertNotSame($originalToken, $session->token());
}
/**
@@ -300,14 +300,14 @@ public function testDuration()
$session->commit();
$originalToken = $session->token();
- $this->assertEquals(7777777777, $session->expiryTime());
- $this->assertEquals(6777777777, $session->duration());
+ $this->assertSame(7777777777, $session->expiryTime());
+ $this->assertSame(6777777777, $session->duration());
$this->assertWriteMode(false, $session);
- $this->assertEquals(3600, $session->duration(3600));
- $this->assertEquals(3600, $session->duration());
- $this->assertEquals(1337000000 + 3600, $session->expiryTime()); // timestamp is from mock
+ $this->assertSame(3600, $session->duration(3600));
+ $this->assertSame(3600, $session->duration());
+ $this->assertSame(1337000000 + 3600, $session->expiryTime()); // timestamp is from mock
$this->assertWriteMode(true, $session);
- $this->assertNotEquals($originalToken, $session->token());
+ $this->assertNotSame($originalToken, $session->token());
}
/**
@@ -355,15 +355,15 @@ public function testTimeout()
$session->regenerateToken();
$session->commit();
- $this->assertEquals(1234, $session->timeout());
+ $this->assertSame(1234, $session->timeout());
$this->assertWriteMode(false, $session);
- $this->assertEquals(4321, $session->timeout(4321));
- $this->assertEquals(4321, $session->timeout());
- $this->assertEquals(time(), $activityProperty->getValue($session));
+ $this->assertSame(4321, $session->timeout(4321));
+ $this->assertSame(4321, $session->timeout());
+ $this->assertSame(time(), $activityProperty->getValue($session));
$this->assertWriteMode(true, $session);
$this->assertFalse($session->timeout(false));
$this->assertFalse($session->timeout());
- $this->assertEquals(null, $activityProperty->getValue($session));
+ $this->assertSame(null, $activityProperty->getValue($session));
$this->assertWriteMode(true, $session);
}
@@ -429,17 +429,17 @@ public function testRenewable()
$this->assertFalse($session->renewable(false));
$this->assertFalse($session->renewable());
$this->assertWriteMode(true, $session);
- $this->assertEquals($originalToken, $session->token());
+ $this->assertSame($originalToken, $session->token());
// re-enabling and disabling shouldn't do anything at first
$this->assertTrue($session->renewable(true));
$this->assertTrue($session->renewable());
$this->assertWriteMode(true, $session);
- $this->assertEquals($originalToken, $session->token());
+ $this->assertSame($originalToken, $session->token());
$this->assertFalse($session->renewable(false));
$this->assertFalse($session->renewable());
$this->assertWriteMode(true, $session);
- $this->assertEquals($originalToken, $session->token());
+ $this->assertSame($originalToken, $session->token());
// make time pass by more than half the session duration
MockTime::$time = 1337000040;
@@ -448,11 +448,11 @@ public function testRenewable()
$this->assertTrue($session->renewable(true));
$this->assertTrue($session->renewable());
$this->assertWriteMode(true, $session);
- $this->assertNotEquals($originalToken, $newToken = $session->token());
+ $this->assertNotSame($originalToken, $newToken = $session->token());
$this->assertTrue($session->renewable(true));
$this->assertTrue($session->renewable());
$this->assertWriteMode(true, $session);
- $this->assertEquals($newToken, $session->token());
+ $this->assertSame($newToken, $session->token());
}
/**
@@ -465,24 +465,24 @@ public function testDataMethods()
$session->data()->reload(['someString' => 'someValue', 'someInt' => 123]);
// get
- $this->assertEquals('someValue', $session->get('someString', 'some default'));
- $this->assertEquals('some default', $session->get('someOtherString', 'some default'));
+ $this->assertSame('someValue', $session->get('someString', 'some default'));
+ $this->assertSame('some default', $session->get('someOtherString', 'some default'));
// set
$session->set('someString', 'someOtherValue');
- $this->assertEquals('someOtherValue', $session->data()->get('someString'));
+ $this->assertSame('someOtherValue', $session->data()->get('someString'));
// increment
$session->increment('someInt', 10);
- $this->assertEquals(133, $session->data()->get('someInt'));
+ $this->assertSame(133, $session->data()->get('someInt'));
// decrement
$session->decrement('someInt', 20);
- $this->assertEquals(113, $session->data()->get('someInt'));
+ $this->assertSame(113, $session->data()->get('someInt'));
// pull
- $this->assertEquals('someOtherValue', $session->pull('someString', 'some default'));
- $this->assertEquals('some default', $session->data()->get('someString', 'some default'));
+ $this->assertSame('someOtherValue', $session->pull('someString', 'some default'));
+ $this->assertSame('some default', $session->data()->get('someString', 'some default'));
// remove
$session->remove('someInt');
@@ -490,9 +490,9 @@ public function testDataMethods()
// clear
$session->data()->reload(['someString' => 'someValue']);
- $this->assertEquals(['someString' => 'someValue'], $session->get());
+ $this->assertSame(['someString' => 'someValue'], $session->get());
$session->clear();
- $this->assertEquals([], $session->get());
+ $this->assertSame([], $session->get());
}
/**
@@ -529,7 +529,7 @@ public function testCommit()
$this->assertWriteMode(false, $session);
$this->assertFalse(isset($this->store->isLocked['9999999999.valid']));
- $this->assertEquals([
+ $this->assertSame([
'startTime' => 0,
'expiryTime' => 9999999999,
'duration' => 9999999999,
@@ -561,15 +561,15 @@ public function testCommit()
$session->renewable(false);
$this->assertWriteMode(true, $session);
$this->assertTrue(isset($this->store->isLocked['9999999999.valid']));
- $this->assertEquals(1234, $session->timeout());
- $this->assertEquals(false, $session->renewable());
- $this->assertEquals('aDifferentValue', $session->data()->get('someKey'));
+ $this->assertSame(1234, $session->timeout());
+ $this->assertSame(false, $session->renewable());
+ $this->assertSame('aDifferentValue', $session->data()->get('someKey'));
$session->commit();
$this->assertWriteMode(false, $session);
$this->assertFalse(isset($this->store->isLocked['9999999999.valid']));
- $this->assertEquals([
+ $this->assertSame([
'startTime' => 0,
'expiryTime' => 9999999999,
'duration' => 9999999999,
@@ -636,18 +636,18 @@ public function testRenew()
$originalToken = $session->token();
$this->assertWriteMode(false, $session);
- $this->assertEquals(9999999999, $session->expiryTime());
- $this->assertEquals(8999999999, $session->duration());
+ $this->assertSame(9999999999, $session->expiryTime());
+ $this->assertSame(8999999999, $session->duration());
$session->renew();
- $this->assertEquals(1337000000 + 8999999999, $session->expiryTime()); // timestamp is from mock
- $this->assertEquals(8999999999, $session->duration());
+ $this->assertSame(1337000000 + 8999999999, $session->expiryTime()); // timestamp is from mock
+ $this->assertSame(8999999999, $session->duration());
$this->assertWriteMode(true, $session);
- $this->assertNotEquals($originalToken, $session->token());
+ $this->assertNotSame($originalToken, $session->token());
// validate that the old session now references the new one
$oldTokenParts = explode('.', $originalToken);
$newTokenParts = explode('.', $session->token());
- $this->assertEquals([
+ $this->assertSame([
'startTime' => 1000000000,
'expiryTime' => 1337000000 + 30, // timestamp is from mock
'newSession' => $newTokenParts[0] . '.' . $newTokenParts[1]
@@ -684,31 +684,31 @@ public function testRegenerateToken()
$this->assertWriteMode(false, $session);
$session->regenerateToken();
- $this->assertNotEquals($token, $newToken = $session->token());
- $this->assertEquals(0, $session->startTime());
- $this->assertEquals(9999999999, $session->expiryTime());
+ $this->assertNotSame($token, $newToken = $session->token());
+ $this->assertSame(0, $session->startTime());
+ $this->assertSame(9999999999, $session->expiryTime());
$this->assertWriteMode(true, $session);
// validate that all parts of the token have been regenerated
$newTokenParts = explode('.', $newToken);
- $this->assertEquals(9999999999, $newTokenParts[0]);
- $this->assertNotEquals('valid', $newTokenParts[1]);
+ $this->assertSame('9999999999', $newTokenParts[0]);
+ $this->assertNotSame('valid', $newTokenParts[1]);
$this->assertStringMatchesFormat('%x', $newTokenParts[1]);
- $this->assertNotEquals($this->store->validKey, $newTokenParts[2]);
+ $this->assertNotSame($this->store->validKey, $newTokenParts[2]);
// validate that the old session now references the new one
- $this->assertEquals([
+ $this->assertSame([
'startTime' => 0,
'expiryTime' => 1337000000 + 30, // timestamp is from mock
'newSession' => $newTokenParts[0] . '.' . $newTokenParts[1]
], $this->store->sessions['9999999999.valid']);
// validate that a cookie has been set
- $this->assertEquals($newToken, Cookie::get('kirby_session'));
+ $this->assertSame($newToken, Cookie::get('kirby_session'));
// validate that the new session is cached in the $sessions object
$this->assertArrayHasKey($newToken, $cache->getValue($this->sessions));
- $this->assertEquals($session, $cache->getValue($this->sessions)[$newToken]);
+ $this->assertSame($session, $cache->getValue($this->sessions)[$newToken]);
}
/**
@@ -727,13 +727,13 @@ public function testRegenerateTokenHeaderMode()
Cookie::remove('kirby_session');
$this->assertFalse($session->needsRetransmission());
$session->regenerateToken();
- $this->assertNotEquals($token, $newToken = $session->token());
+ $this->assertNotSame($token, $newToken = $session->token());
$this->assertTrue($session->needsRetransmission());
$this->assertNull(Cookie::get('kirby_session'));
// validate that the new session is cached in the $sessions object
$this->assertArrayHasKey($newToken, $cache->getValue($this->sessions));
- $this->assertEquals($session, $cache->getValue($this->sessions)[$newToken]);
+ $this->assertSame($session, $cache->getValue($this->sessions)[$newToken]);
}
/**
@@ -751,7 +751,7 @@ public function testDestruct()
$this->assertFalse(isset($this->store->sessions['9999999999.valid']['data']['someId']));
$session->__destruct(); // actually destructing is not possible in the test (we need to access the store later)
- $this->assertEquals(1, $this->store->sessions['9999999999.valid']['data']['someId']);
+ $this->assertSame(1, $this->store->sessions['9999999999.valid']['data']['someId']);
}
/**
@@ -765,19 +765,19 @@ public function testPrepareForWriting()
$this->assertWriteMode(false, $session);
$this->assertFalse(isset($this->store->isLocked['9999999999.valid']));
- $this->assertEquals(null, $session->data()->get('someId'));
+ $this->assertSame(null, $session->data()->get('someId'));
// manually overwrite some data like another thread would do
$this->store->sessions['9999999999.valid']['data']['someId'] = 123;
$this->assertWriteMode(false, $session);
$this->assertFalse(isset($this->store->isLocked['9999999999.valid']));
- $this->assertEquals(null, $session->data()->get('someId'));
+ $this->assertSame(null, $session->data()->get('someId'));
// now trigger a reload of the session by setting a value
$session->data()->increment('someId', 1);
$this->assertWriteMode(true, $session);
$this->assertTrue(isset($this->store->isLocked['9999999999.valid']));
- $this->assertEquals(124, $session->data()->get('someId'));
+ $this->assertSame(124, $session->data()->get('someId'));
}
/**
@@ -812,12 +812,12 @@ public function testParseToken()
// full token
$parseToken->invoke($session, '1234567890.thisIsMyAwesomeId.' . $this->store->validKey);
- $this->assertEquals('1234567890.thisIsMyAwesomeId.' . $this->store->validKey, $session->token());
- $this->assertEquals($this->store->validKey, $tokenKey->getValue($session));
+ $this->assertSame('1234567890.thisIsMyAwesomeId.' . $this->store->validKey, $session->token());
+ $this->assertSame($this->store->validKey, $tokenKey->getValue($session));
// token without key
$parseToken->invoke($session, '1234567890.thisIsMyAwesomeId', true);
- $this->assertEquals('1234567890.thisIsMyAwesomeId', $session->token());
+ $this->assertSame('1234567890.thisIsMyAwesomeId', $session->token());
$this->assertNull($tokenKey->getValue($session));
}
@@ -870,11 +870,11 @@ public function testTimeToTimestamp()
$timeToTimestamp = $reflector->getMethod('timeToTimestamp');
$timeToTimestamp->setAccessible(true);
- $this->assertEquals(1234567890, $timeToTimestamp->invoke(null, 1234567890));
- $this->assertEquals(1234567890, $timeToTimestamp->invoke(null, 1234567890, 1357924680));
- $this->assertEquals(1514764800, $timeToTimestamp->invoke(null, '2018-01-01T00:00:00+00:00', 1357924680));
- $this->assertEquals(strtotime('tomorrow', 1337000000), $timeToTimestamp->invoke(null, 'tomorrow')); // timestamp is from mock
- $this->assertEquals(strtotime('tomorrow', 1357924680), $timeToTimestamp->invoke(null, 'tomorrow', 1357924680));
+ $this->assertSame(1234567890, $timeToTimestamp->invoke(null, 1234567890));
+ $this->assertSame(1234567890, $timeToTimestamp->invoke(null, 1234567890, 1357924680));
+ $this->assertSame(1514764800, $timeToTimestamp->invoke(null, '2018-01-01T00:00:00+00:00', 1357924680));
+ $this->assertSame(strtotime('tomorrow', 1337000000), $timeToTimestamp->invoke(null, 'tomorrow')); // timestamp is from mock
+ $this->assertSame(strtotime('tomorrow', 1357924680), $timeToTimestamp->invoke(null, 'tomorrow', 1357924680));
}
/**
@@ -919,13 +919,13 @@ public function testInit()
$token = '9999999999.valid.' . $this->store->validKey;
$session = new Session($this->sessions, $token, []);
- $this->assertEquals($token, $session->token());
- $this->assertEquals(0, $session->startTime());
- $this->assertEquals(9999999999, $session->expiryTime());
- $this->assertEquals(9999999999, $session->duration());
+ $this->assertSame($token, $session->token());
+ $this->assertSame(0, $session->startTime());
+ $this->assertSame(9999999999, $session->expiryTime());
+ $this->assertSame(9999999999, $session->duration());
$this->assertFalse($session->timeout());
$this->assertFalse($session->renewable());
- $this->assertEquals('valid', $session->data()->get('id'));
+ $this->assertSame('valid', $session->data()->get('id'));
}
/**
@@ -947,15 +947,15 @@ public function testInitSerializedObject()
$session->data()->set('obj', $obj);
$this->assertWriteMode(true, $session);
$this->assertInstanceOf(Obj::class, $session->data()->get('obj'));
- $this->assertEquals($obj, $session->data()->get('obj'));
+ $this->assertSame($obj, $session->data()->get('obj'));
$this->assertTrue($obj === $session->data()->get('obj'));
$session->commit();
$this->assertWriteMode(false, $session);
$session = new Session($this->sessions, $token, []);
- $this->assertEquals('test-session', $session->data()->get('name'));
+ $this->assertSame('test-session', $session->data()->get('name'));
$this->assertInstanceOf(Obj::class, $session->data()->get('obj'));
- $this->assertEquals($obj, $session->data()->get('obj'));
+ $this->assertEquals($obj, $session->data()->get('obj')); // cannot use strict test
$this->assertFalse($obj === $session->data()->get('obj'));
}
@@ -1063,13 +1063,13 @@ public function testInitMoved()
$token = '9999999999.moved.' . $this->store->validKey;
$session = new Session($this->sessions, $token, []);
- $this->assertEquals('9999999999.valid', $session->token());
- $this->assertEquals(0, $session->startTime());
- $this->assertEquals(9999999999, $session->expiryTime());
- $this->assertEquals(9999999999, $session->duration());
+ $this->assertSame('9999999999.valid', $session->token());
+ $this->assertSame(0, $session->startTime());
+ $this->assertSame(9999999999, $session->expiryTime());
+ $this->assertSame(9999999999, $session->duration());
$this->assertFalse($session->timeout());
$this->assertFalse($session->renewable());
- $this->assertEquals('valid', $session->data()->get('id'));
+ $this->assertSame('valid', $session->data()->get('id'));
}
/**
@@ -1085,13 +1085,13 @@ public function testInitMovedRenewal()
$token = '9999999999.movedRenewal.' . $this->store->validKey;
$session = new Session($this->sessions, $token, []);
- $this->assertEquals('2000000000.renewal', $session->token());
- $this->assertEquals(0, $session->startTime());
- $this->assertEquals(2000000000, $session->expiryTime());
- $this->assertEquals(2000000000, $session->duration());
+ $this->assertSame('2000000000.renewal', $session->token());
+ $this->assertSame(0, $session->startTime());
+ $this->assertSame(2000000000, $session->expiryTime());
+ $this->assertSame(2000000000, $session->duration());
$this->assertFalse($session->timeout());
$this->assertTrue($session->renewable());
- $this->assertEquals('renewal', $session->data()->get('id'));
+ $this->assertSame('renewal', $session->data()->get('id'));
// new session should *not* be renewed because the new session is read-only
$this->assertWriteMode(false, $session);
@@ -1125,13 +1125,13 @@ public function testInitTimeoutActivity()
$token = '9999999999.movedTimeoutActivity.' . $this->store->validKey;
$session = new Session($this->sessions, $token, []);
- $this->assertEquals('9999999999.timeoutActivity2', $session->token());
- $this->assertEquals(0, $session->startTime());
- $this->assertEquals(9999999999, $session->expiryTime());
- $this->assertEquals(9999999999, $session->duration());
- $this->assertEquals(3600, $session->timeout());
+ $this->assertSame('9999999999.timeoutActivity2', $session->token());
+ $this->assertSame(0, $session->startTime());
+ $this->assertSame(9999999999, $session->expiryTime());
+ $this->assertSame(9999999999, $session->duration());
+ $this->assertSame(3600, $session->timeout());
$this->assertFalse($session->renewable());
- $this->assertEquals('timeoutActivity2', $session->data()->get('id'));
+ $this->assertSame('timeoutActivity2', $session->data()->get('id'));
// new session should *not* be refreshed because the new session is read-only
$this->assertWriteMode(false, $session);
@@ -1201,18 +1201,18 @@ public function testInitAutoActivity1()
$token = '9999999999.timeoutActivity1.' . $this->store->validKey;
$session = new Session($this->sessions, $token, []);
- $this->assertEquals($token, $session->token());
- $this->assertEquals(0, $session->startTime());
- $this->assertEquals(9999999999, $session->expiryTime());
- $this->assertEquals(9999999999, $session->duration());
- $this->assertEquals(3600, $session->timeout());
+ $this->assertSame($token, $session->token());
+ $this->assertSame(0, $session->startTime());
+ $this->assertSame(9999999999, $session->expiryTime());
+ $this->assertSame(9999999999, $session->duration());
+ $this->assertSame(3600, $session->timeout());
$this->assertFalse($session->renewable());
- $this->assertEquals('timeoutActivity1', $session->data()->get('id'));
+ $this->assertSame('timeoutActivity1', $session->data()->get('id'));
$reflector = new ReflectionClass(Session::class);
$activityProperty = $reflector->getProperty('lastActivity');
$activityProperty->setAccessible(true);
- $this->assertEquals($session->data()->get('expectedActivity'), $activityProperty->getValue($session));
+ $this->assertSame($session->data()->get('expectedActivity'), $activityProperty->getValue($session));
}
/**
@@ -1227,13 +1227,13 @@ public function testInitAutoActivity2()
$token = '9999999999.timeoutActivity2.' . $this->store->validKey;
$session = new Session($this->sessions, $token, []);
- $this->assertEquals($token, $session->token());
- $this->assertEquals(0, $session->startTime());
- $this->assertEquals(9999999999, $session->expiryTime());
- $this->assertEquals(9999999999, $session->duration());
- $this->assertEquals(3600, $session->timeout());
+ $this->assertSame($token, $session->token());
+ $this->assertSame(0, $session->startTime());
+ $this->assertSame(9999999999, $session->expiryTime());
+ $this->assertSame(9999999999, $session->duration());
+ $this->assertSame(3600, $session->timeout());
$this->assertFalse($session->renewable());
- $this->assertEquals('timeoutActivity2', $session->data()->get('id'));
+ $this->assertSame('timeoutActivity2', $session->data()->get('id'));
$reflector = new ReflectionClass(Session::class);
$activityProperty = $reflector->getProperty('lastActivity');
@@ -1258,13 +1258,13 @@ public function testInitAutoRenew()
$newToken = $session->token();
$newTokenExpiry = (int)Str::before($newToken, '.');
- $this->assertEquals(1337000000 + 2000000000, $newTokenExpiry); // timestamp is from mock
- $this->assertEquals(0, $session->startTime());
- $this->assertEquals($newTokenExpiry, $session->expiryTime());
- $this->assertEquals(2000000000, $session->duration());
+ $this->assertSame(1337000000 + 2000000000, $newTokenExpiry); // timestamp is from mock
+ $this->assertSame(0, $session->startTime());
+ $this->assertSame($newTokenExpiry, $session->expiryTime());
+ $this->assertSame(2000000000, $session->duration());
$this->assertFalse($session->timeout());
$this->assertTrue($session->renewable());
- $this->assertEquals('renewal', $session->data()->get('id'));
+ $this->assertSame('renewal', $session->data()->get('id'));
}
/**
@@ -1279,20 +1279,20 @@ public function testInitNonRenewable()
$token = '2000000000.nonRenewable.' . $this->store->validKey;
$session = new Session($this->sessions, $token, []);
- $this->assertEquals($token, $session->token());
- $this->assertEquals(0, $session->startTime());
- $this->assertEquals(2000000000, $session->expiryTime());
- $this->assertEquals(2000000000, $session->duration());
+ $this->assertSame($token, $session->token());
+ $this->assertSame(0, $session->startTime());
+ $this->assertSame(2000000000, $session->expiryTime());
+ $this->assertSame(2000000000, $session->duration());
$this->assertFalse($session->timeout());
$this->assertFalse($session->renewable());
- $this->assertEquals('nonRenewable', $session->data()->get('id'));
+ $this->assertSame('nonRenewable', $session->data()->get('id'));
}
/**
* Asserts the state of the write mode of the given session
*
- * @param boolean $expected Whether the write mode should be true or false right now
- * @param Session $session
+ * @param bool $expected Whether the write mode should be true or false right now
+ * @param Session $session
* @return void
*/
protected function assertWriteMode(bool $expected, Session $session)
@@ -1301,6 +1301,6 @@ protected function assertWriteMode(bool $expected, Session $session)
$writeModeProperty = $reflector->getProperty('writeMode');
$writeModeProperty->setAccessible(true);
- $this->assertEquals($expected, $writeModeProperty->getValue($session));
+ $this->assertSame($expected, $writeModeProperty->getValue($session));
}
}
diff --git a/tests/Session/SessionsTest.php b/tests/Session/SessionsTest.php
index 5260712063..61ea76acd4 100644
--- a/tests/Session/SessionsTest.php
+++ b/tests/Session/SessionsTest.php
@@ -36,12 +36,12 @@ public function tearDown(): void
public function testConstructorStores()
{
// mock store
- $this->assertEquals($this->store, $this->sessions->store());
+ $this->assertSame($this->store, $this->sessions->store());
// custom store
$store = new FileSessionStore(__DIR__ . '/fixtures/store');
$sessions = new Sessions($store);
- $this->assertEquals($store, $sessions->store());
+ $this->assertSame($store, $sessions->store());
// custom path
$path = __DIR__ . '/fixtures/store';
@@ -50,7 +50,7 @@ public function testConstructorStores()
$reflector = new ReflectionClass(FileSessionStore::class);
$pathProperty = $reflector->getProperty('path');
$pathProperty->setAccessible(true);
- $this->assertEquals($path, $pathProperty->getValue($sessions->store()));
+ $this->assertSame($path, $pathProperty->getValue($sessions->store()));
}
/**
@@ -74,12 +74,12 @@ public function testConstructorOptions()
'cookieName' => 'my_cookie_name'
]);
- $this->assertEquals('my_cookie_name', $sessions->cookieName());
+ $this->assertSame('my_cookie_name', $sessions->cookieName());
$reflector = new ReflectionClass(Sessions::class);
$modeProperty = $reflector->getProperty('mode');
$modeProperty->setAccessible(true);
- $this->assertEquals('header', $modeProperty->getValue($sessions));
+ $this->assertSame('header', $modeProperty->getValue($sessions));
}
/**
@@ -135,12 +135,12 @@ public function testCreate()
{
$sessions = new Sessions($this->store, ['mode' => 'header']);
$session = $sessions->create();
- $this->assertEquals('header', $session->mode());
+ $this->assertSame('header', $session->mode());
$this->assertNull($session->token());
- $this->assertEquals(1337000000, $session->startTime()); // timestamp is from mock
- $this->assertEquals(7200, $session->duration());
- $this->assertEquals(1337000000 + 7200, $session->expiryTime()); // timestamp is from mock
- $this->assertEquals(1800, $session->timeout());
+ $this->assertSame(1337000000, $session->startTime()); // timestamp is from mock
+ $this->assertSame(7200, $session->duration());
+ $this->assertSame(1337000000 + 7200, $session->expiryTime()); // timestamp is from mock
+ $this->assertSame(1800, $session->timeout());
$this->assertTrue($session->renewable());
$session = $sessions->create([
@@ -150,12 +150,12 @@ public function testCreate()
'timeout' => false,
'renewable' => false
]);
- $this->assertEquals('manual', $session->mode());
+ $this->assertSame('manual', $session->mode());
$this->assertNull($session->token());
- $this->assertEquals(1337000000 + 3600, $session->startTime()); // timestamp is from mock
- $this->assertEquals(36000, $session->duration());
- $this->assertEquals(1337000000 + 39600, $session->expiryTime()); // timestamp is from mock
- $this->assertEquals(false, $session->timeout());
+ $this->assertSame(1337000000 + 3600, $session->startTime()); // timestamp is from mock
+ $this->assertSame(36000, $session->duration());
+ $this->assertSame(1337000000 + 39600, $session->expiryTime()); // timestamp is from mock
+ $this->assertSame(false, $session->timeout());
$this->assertFalse($session->renewable());
}
@@ -166,17 +166,17 @@ public function testGet()
{
$sessions = new Sessions($this->store, ['mode' => 'header']);
$session = $sessions->get('9999999999.valid.' . $this->store->validKey);
- $this->assertEquals('header', $session->mode());
- $this->assertEquals('9999999999.valid.' . $this->store->validKey, $session->token());
+ $this->assertSame('header', $session->mode());
+ $this->assertSame('9999999999.valid.' . $this->store->validKey, $session->token());
$session1 = $sessions->get('9999999999.valid2.' . $this->store->validKey, 'manual');
- $this->assertEquals('manual', $session1->mode());
- $this->assertEquals('9999999999.valid2.' . $this->store->validKey, $session1->token());
+ $this->assertSame('manual', $session1->mode());
+ $this->assertSame('9999999999.valid2.' . $this->store->validKey, $session1->token());
$session2 = $sessions->get('9999999999.valid2.' . $this->store->validKey, 'header');
- $this->assertEquals($session1, $session2);
+ $this->assertSame($session1, $session2);
$session1->data()->set('someKey', 'someValue');
- $this->assertEquals('someValue', $session2->data()->get('someKey'));
+ $this->assertSame('someValue', $session2->data()->get('someKey'));
}
/**
@@ -200,13 +200,13 @@ public function testCurrent()
$sessions = new Sessions($this->store, ['mode' => 'cookie']);
$session = $sessions->current();
- $this->assertEquals('cookie', $session->mode());
- $this->assertEquals('9999999999.valid.' . $this->store->validKey, $session->token());
+ $this->assertSame('cookie', $session->mode());
+ $this->assertSame('9999999999.valid.' . $this->store->validKey, $session->token());
$sessions = new Sessions($this->store, ['mode' => 'header']);
$session = $sessions->current();
- $this->assertEquals('header', $session->mode());
- $this->assertEquals('9999999999.valid2.' . $this->store->validKey, $session->token());
+ $this->assertSame('header', $session->mode());
+ $this->assertSame('9999999999.valid2.' . $this->store->validKey, $session->token());
unset($_SERVER['HTTP_AUTHORIZATION']);
$this->assertNull($sessions->current());
@@ -217,8 +217,8 @@ public function testCurrent()
// test self-check: should work again
$_SERVER['HTTP_AUTHORIZATION'] = 'Session 9999999999.valid2.' . $this->store->validKey;
$session = $sessions->current();
- $this->assertEquals('header', $session->mode());
- $this->assertEquals('9999999999.valid2.' . $this->store->validKey, $session->token());
+ $this->assertSame('header', $session->mode());
+ $this->assertSame('9999999999.valid2.' . $this->store->validKey, $session->token());
}
/**
@@ -242,13 +242,13 @@ public function testCurrentDetected()
$_SERVER['HTTP_AUTHORIZATION'] = 'Session 9999999999.valid2.' . $this->store->validKey;
$session = $this->sessions->currentDetected();
- $this->assertEquals('header', $session->mode());
- $this->assertEquals('9999999999.valid2.' . $this->store->validKey, $session->token());
+ $this->assertSame('header', $session->mode());
+ $this->assertSame('9999999999.valid2.' . $this->store->validKey, $session->token());
unset($_SERVER['HTTP_AUTHORIZATION']);
$session = $this->sessions->currentDetected();
- $this->assertEquals('cookie', $session->mode());
- $this->assertEquals('9999999999.valid.' . $this->store->validKey, $session->token());
+ $this->assertSame('cookie', $session->mode());
+ $this->assertSame('9999999999.valid.' . $this->store->validKey, $session->token());
Cookie::remove('kirby_session');
$this->assertNull($this->sessions->currentDetected());
@@ -260,8 +260,8 @@ public function testCurrentDetected()
// test self-check: should work again
$_SERVER['HTTP_AUTHORIZATION'] = 'Session 9999999999.valid2.' . $this->store->validKey;
$session = $this->sessions->currentDetected();
- $this->assertEquals('header', $session->mode());
- $this->assertEquals('9999999999.valid2.' . $this->store->validKey, $session->token());
+ $this->assertSame('header', $session->mode());
+ $this->assertSame('9999999999.valid2.' . $this->store->validKey, $session->token());
}
/**
@@ -294,7 +294,7 @@ public function testUpdateCache()
$this->assertArrayNotHasKey('9999999999.valid.new-key', $cache->getValue($sessions));
$sessions->updateCache($session);
$this->assertArrayHasKey('9999999999.valid.new-key', $cache->getValue($sessions));
- $this->assertEquals($session, $cache->getValue($sessions)['9999999999.valid.new-key']);
+ $this->assertSame($session, $cache->getValue($sessions)['9999999999.valid.new-key']);
}
/**
@@ -310,7 +310,7 @@ public function testTokenFromCookie()
$this->assertNull($tokenFromCookie->invoke($this->sessions));
Cookie::set('kirby_session', 'amazingSessionIdFromCookie');
- $this->assertEquals('amazingSessionIdFromCookie', $tokenFromCookie->invoke($this->sessions));
+ $this->assertSame('amazingSessionIdFromCookie', $tokenFromCookie->invoke($this->sessions));
Cookie::remove('kirby_session');
}
@@ -328,7 +328,7 @@ public function testTokenFromHeader()
$this->assertNull($tokenFromHeader->invoke($this->sessions));
$_SERVER['HTTP_AUTHORIZATION'] = 'Session amazingSessionIdFromHeader';
- $this->assertEquals('amazingSessionIdFromHeader', $tokenFromHeader->invoke($this->sessions));
+ $this->assertSame('amazingSessionIdFromHeader', $tokenFromHeader->invoke($this->sessions));
$_SERVER['HTTP_AUTHORIZATION'] = 'Bearer amazingSessionIdFromHeader';
$this->assertNull($tokenFromHeader->invoke($this->sessions));
diff --git a/tests/Text/KirbyTagTest.php b/tests/Text/KirbyTagTest.php
index 2902b3b001..2653099b09 100644
--- a/tests/Text/KirbyTagTest.php
+++ b/tests/Text/KirbyTagTest.php
@@ -44,9 +44,9 @@ public function test__call()
$tag = new KirbyTag('test', 'test value', $attr, $data);
- $this->assertEquals('dataA', $tag->a());
- $this->assertEquals('attrB', $tag->b());
- $this->assertEquals('dataC', $tag->c());
+ $this->assertSame('dataA', $tag->a());
+ $this->assertSame('attrB', $tag->b());
+ $this->assertSame('dataC', $tag->c());
}
public function test__callStatic()
@@ -58,7 +58,7 @@ public function test__callStatic()
$result = KirbyTag::test('test value', $attr);
- $this->assertEquals('test: test value-attrA-attrB', $result);
+ $this->assertSame('test: test value-attrA-attrB', $result);
}
public function testAttr()
@@ -69,12 +69,12 @@ public function testAttr()
]);
// class properties
- $this->assertEquals('attrA', $tag->a);
- $this->assertEquals('attrB', $tag->b);
+ $this->assertSame('attrA', $tag->a);
+ $this->assertSame('attrB', $tag->b);
// attr helper
- $this->assertEquals('attrA', $tag->attr('a', 'fallback'));
- $this->assertEquals('attrB', $tag->attr('b', 'fallback'));
+ $this->assertSame('attrA', $tag->attr('a', 'fallback'));
+ $this->assertSame('attrB', $tag->attr('b', 'fallback'));
}
public function testAttrFallback()
@@ -84,7 +84,7 @@ public function testAttrFallback()
]);
$this->assertNull($tag->b);
- $this->assertEquals('fallback', $tag->attr('b', 'fallback'));
+ $this->assertSame('fallback', $tag->attr('b', 'fallback'));
}
public function testFactory()
@@ -96,7 +96,7 @@ public function testFactory()
$result = KirbyTag::factory('test', 'test value', $attr);
- $this->assertEquals('test: test value-attrA-attrB', $result);
+ $this->assertSame('test: test value-attrA-attrB', $result);
}
public function testOption()
@@ -118,87 +118,87 @@ public function testOption()
$tag = new KirbyTag('test', 'test value', $attr, $data, $options);
- $this->assertEquals('optionA', $tag->option('a'));
- $this->assertEquals('optionB', $tag->option('b'));
- $this->assertEquals('optionC', $tag->option('c', 'optionC'));
+ $this->assertSame('optionA', $tag->option('a'));
+ $this->assertSame('optionB', $tag->option('b'));
+ $this->assertSame('optionC', $tag->option('c', 'optionC'));
}
public function testParse()
{
$tag = KirbyTag::parse('(test: test value)', ['some' => 'data'], ['some' => 'options']);
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('test value', $tag->value);
- $this->assertEquals(['some' => 'data'], $tag->data);
- $this->assertEquals(['some' => 'options'], $tag->options);
- $this->assertEquals([], $tag->attrs);
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('test value', $tag->value);
+ $this->assertSame(['some' => 'data'], $tag->data);
+ $this->assertSame(['some' => 'options'], $tag->options);
+ $this->assertSame([], $tag->attrs);
$tag = KirbyTag::parse('test: test value');
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('test value', $tag->value);
- $this->assertEquals([], $tag->attrs);
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('test value', $tag->value);
+ $this->assertSame([], $tag->attrs);
$tag = KirbyTag::parse('test:');
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('', $tag->value);
- $this->assertEquals([], $tag->attrs);
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('', $tag->value);
+ $this->assertSame([], $tag->attrs);
$tag = KirbyTag::parse('test: ');
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('', $tag->value);
- $this->assertEquals([], $tag->attrs);
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('', $tag->value);
+ $this->assertSame([], $tag->attrs);
$tag = KirbyTag::parse('test: test value a: attrA b: attrB');
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('test value', $tag->value);
- $this->assertEquals([
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('test value', $tag->value);
+ $this->assertSame([
'a' => 'attrA',
'b' => 'attrB'
], $tag->attrs);
$tag = KirbyTag::parse('test:test value a:attrA b:attrB');
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('test value', $tag->value);
- $this->assertEquals([
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('test value', $tag->value);
+ $this->assertSame([
'a' => 'attrA',
'b' => 'attrB'
], $tag->attrs);
$tag = KirbyTag::parse('test: test value a: attrA b:');
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('test value', $tag->value);
- $this->assertEquals([
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('test value', $tag->value);
+ $this->assertSame([
'a' => 'attrA',
'b' => ''
], $tag->attrs);
$tag = KirbyTag::parse('test: test value a: attrA b: ');
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('test value', $tag->value);
- $this->assertEquals([
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('test value', $tag->value);
+ $this->assertSame([
'a' => 'attrA',
'b' => ''
], $tag->attrs);
$tag = KirbyTag::parse('test: test value a: attrA b: attrB ');
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('test value', $tag->value);
- $this->assertEquals([
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('test value', $tag->value);
+ $this->assertSame([
'a' => 'attrA',
'b' => 'attrB'
], $tag->attrs);
$tag = KirbyTag::parse('test: test value a: attrA c: attrC b: attrB');
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('test value', $tag->value);
- $this->assertEquals([
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('test value', $tag->value);
+ $this->assertSame([
'a' => 'attrA c: attrC',
'b' => 'attrB'
], $tag->attrs);
$tag = KirbyTag::parse('test: test value a: attrA b: attrB c: attrC');
- $this->assertEquals('test', $tag->type);
- $this->assertEquals('test value', $tag->value);
- $this->assertEquals([
+ $this->assertSame('test', $tag->type);
+ $this->assertSame('test value', $tag->value);
+ $this->assertSame([
'a' => 'attrA',
'b' => 'attrB c: attrC'
], $tag->attrs);
@@ -218,12 +218,12 @@ public function testRender()
'a' => 'attrA',
'b' => 'attrB'
]);
- $this->assertEquals('test: test value-attrA-attrB', $tag->render());
+ $this->assertSame('test: test value-attrA-attrB', $tag->render());
$tag = new KirbyTag('test', '', [
'a' => 'attrA'
]);
- $this->assertEquals('test: -attrA-', $tag->render());
+ $this->assertSame('test: -attrA-', $tag->render());
}
public function testRenderNoHtml()
@@ -253,6 +253,6 @@ public function testRenderInvalidHtml()
public function testType()
{
$tag = new KirbyTag('test', 'test value');
- $this->assertEquals('test', $tag->type());
+ $this->assertSame('test', $tag->type());
}
}
diff --git a/tests/Text/KirbyTagsTest.php b/tests/Text/KirbyTagsTest.php
index fb8750b4cb..f86a0e825e 100644
--- a/tests/Text/KirbyTagsTest.php
+++ b/tests/Text/KirbyTagsTest.php
@@ -17,10 +17,10 @@ public function testParse()
]
];
- $this->assertEquals('test', KirbyTags::parse('(test: foo)'));
- $this->assertEquals('test', KirbyTags::parse('(Test: foo)'));
- $this->assertEquals('test', KirbyTags::parse('(TEST: foo)'));
- $this->assertEquals('test', KirbyTags::parse('(tEsT: foo)'));
+ $this->assertSame('test', KirbyTags::parse('(test: foo)'));
+ $this->assertSame('test', KirbyTags::parse('(Test: foo)'));
+ $this->assertSame('test', KirbyTags::parse('(TEST: foo)'));
+ $this->assertSame('test', KirbyTags::parse('(tEsT: foo)'));
}
public function testParseWithValue()
@@ -33,9 +33,9 @@ public function testParseWithValue()
]
];
- $this->assertEquals('foo', KirbyTags::parse('(test: foo)'));
- $this->assertEquals('foo', KirbyTags::parse('(Test: foo)'));
- $this->assertEquals('foo', KirbyTags::parse('(TEST: foo)'));
+ $this->assertSame('foo', KirbyTags::parse('(test: foo)'));
+ $this->assertSame('foo', KirbyTags::parse('(Test: foo)'));
+ $this->assertSame('foo', KirbyTags::parse('(TEST: foo)'));
}
public function testParseWithAttribute()
@@ -49,9 +49,9 @@ public function testParseWithAttribute()
]
];
- $this->assertEquals('foo|bar', KirbyTags::parse('(test: foo a: bar)'));
- $this->assertEquals('foo|bar', KirbyTags::parse('(Test: foo A: bar)'));
- $this->assertEquals('foo|bar', KirbyTags::parse('(TEST: foo a: bar)'));
+ $this->assertSame('foo|bar', KirbyTags::parse('(test: foo a: bar)'));
+ $this->assertSame('foo|bar', KirbyTags::parse('(Test: foo A: bar)'));
+ $this->assertSame('foo|bar', KirbyTags::parse('(TEST: foo a: bar)'));
}
public function testParseWithException()
@@ -64,6 +64,6 @@ public function testParseWithException()
]
];
- $this->assertEquals('(test: foo)', KirbyTags::parse('(test: foo)'));
+ $this->assertSame('(test: foo)', KirbyTags::parse('(test: foo)'));
}
}
diff --git a/tests/Text/MarkdownTest.php b/tests/Text/MarkdownTest.php
index 5f4318c67a..2ed8fe3c2e 100644
--- a/tests/Text/MarkdownTest.php
+++ b/tests/Text/MarkdownTest.php
@@ -12,7 +12,7 @@ public function testDefaults()
{
$markdown = new Markdown();
- $this->assertEquals([
+ $this->assertSame([
'extra' => false,
'breaks' => true
], $markdown->defaults());
@@ -33,7 +33,7 @@ public function testParse()
$markdown = new Markdown();
$md = file_get_contents(static::FIXTURES . '/markdown.md');
$html = file_get_contents(static::FIXTURES . '/markdown.html');
- $this->assertEquals($html, $markdown->parse($md));
+ $this->assertSame($html, $markdown->parse($md));
}
public function testParseWithExtra()
@@ -41,7 +41,7 @@ public function testParseWithExtra()
$markdown = new Markdown(['extra' => true]);
$md = file_get_contents(static::FIXTURES . '/markdown.md');
$html = file_get_contents(static::FIXTURES . '/markdownextra.html');
- $this->assertEquals($html, $markdown->parse($md));
+ $this->assertSame($html, $markdown->parse($md));
}
public function testParseWithoutBreaks()
@@ -49,6 +49,6 @@ public function testParseWithoutBreaks()
$markdown = new Markdown(['breaks' => false]);
$md = file_get_contents(static::FIXTURES . '/markdown.md');
$html = file_get_contents(static::FIXTURES . '/markdownbreaks.html');
- $this->assertEquals($html, $markdown->parse($md));
+ $this->assertSame($html, $markdown->parse($md));
}
}
diff --git a/tests/Text/SmartyPantsTest.php b/tests/Text/SmartyPantsTest.php
index 312ee1e44c..34eb28407b 100644
--- a/tests/Text/SmartyPantsTest.php
+++ b/tests/Text/SmartyPantsTest.php
@@ -12,7 +12,7 @@ public function testParse()
$result = $parser->parse('This is a "test quote"');
$expected = 'This is a “test quote”';
- $this->assertEquals($expected, $result);
+ $this->assertSame($expected, $result);
}
public function testDefaults()
@@ -49,7 +49,7 @@ public function testDefaults()
$parser = new SmartyPants();
- $this->assertEquals($expected, $parser->defaults());
+ $this->assertSame($expected, $parser->defaults());
}
public function testDoubleQuotesOption()
@@ -60,7 +60,7 @@ public function testDoubleQuotesOption()
]);
$result = $parser->parse('"test"');
- $this->assertEquals('', $result);
+ $this->assertSame('', $result);
}
public function testSingleQuotesOption()
@@ -71,7 +71,7 @@ public function testSingleQuotesOption()
]);
$result = $parser->parse("'test'");
- $this->assertEquals('', $result);
+ $this->assertSame('', $result);
}
public function testEmDashOption()
@@ -81,7 +81,7 @@ public function testEmDashOption()
]);
$result = $parser->parse('--');
- $this->assertEquals('emdash', $result);
+ $this->assertSame('emdash', $result);
}
public function testEllipsisOption()
@@ -91,6 +91,6 @@ public function testEllipsisOption()
]);
$result = $parser->parse('...');
- $this->assertEquals('ellipsis', $result);
+ $this->assertSame('ellipsis', $result);
}
}
diff --git a/tests/Toolkit/ATest.php b/tests/Toolkit/ATest.php
index a207f50861..548092fd2e 100644
--- a/tests/Toolkit/ATest.php
+++ b/tests/Toolkit/ATest.php
@@ -86,26 +86,25 @@ public function testMerge()
{
// simple non-associative arrays
- $this->assertEquals(['a', 'b', 'c', 'd'], a::merge(['a', 'b'], ['c', 'd']));
- $this->assertEquals(['a', 'b', 'c', 'd', 'a'], a::merge(['a', 'b'], ['c', 'd', 'a']));
+ $this->assertEquals(['a', 'b', 'c', 'd'], A::merge(['a', 'b'], ['c', 'd']));
+ $this->assertEquals(['a', 'b', 'c', 'd', 'a'], A::merge(['a', 'b'], ['c', 'd', 'a']));
// simple associative arrays
- $this->assertEquals(['a' => 'b', 'c' => 'd'], a::merge(['a' => 'b'], ['c' => 'd']));
- $this->assertEquals(['a' => 'c'], a::merge(['a' => 'b'], ['a' => 'c']));
- $this->assertEquals(['a' => 'd'], a::merge(['a' => 'b'], ['a' => 'c', 'a' => 'd']));
+ $this->assertEquals(['a' => 'b', 'c' => 'd'], A::merge(['a' => 'b'], ['c' => 'd']));
+ $this->assertEquals(['a' => 'c'], A::merge(['a' => 'b'], ['a' => 'c']));
// recursive merging
- $this->assertEquals(['a' => ['b', 'c', 'b', 'd']], a::merge(['a' => ['b', 'c']], ['a' => ['b', 'd']]));
- $this->assertEquals(['a' => ['b' => 'd', 'd' => 'e']], a::merge(['a' => ['b' => 'c', 'd' => 'e']], ['a' => ['b' => 'd']]));
- $this->assertEquals(['a' => ['b', 'c']], a::merge(['a' => 'b'], ['a' => ['b', 'c']]));
- $this->assertEquals(['a' => 'b'], a::merge(['a' => ['b', 'c']], ['a' => 'b']));
+ $this->assertEquals(['a' => ['b', 'c', 'b', 'd']], A::merge(['a' => ['b', 'c']], ['a' => ['b', 'd']]));
+ $this->assertEquals(['a' => ['b' => 'd', 'd' => 'e']], A::merge(['a' => ['b' => 'c', 'd' => 'e']], ['a' => ['b' => 'd']]));
+ $this->assertEquals(['a' => ['b', 'c']], A::merge(['a' => 'b'], ['a' => ['b', 'c']]));
+ $this->assertEquals(['a' => 'b'], A::merge(['a' => ['b', 'c']], ['a' => 'b']));
// append feature
- $this->assertEquals(['a', 'b', 'c', 'd', 'a'], a::merge([1 => 'a', 4 => 'b'], [1 => 'c', 3 => 'd', 5 => 'a']));
- $this->assertEquals(['a', 'b', 'c', 'd', 'a'], a::merge([1 => 'a', 4 => 'b'], [1 => 'c', 3 => 'd', 5 => 'a'], true));
- $this->assertEquals([1 => 'c', 3 => 'd', 4 => 'b', 5 => 'a'], a::merge([1 => 'a', 4 => 'b'], [1 => 'c', 3 => 'd', 5 => 'a'], false));
- $this->assertEquals(['a' => ['b', 'c', 'e', 'd']], a::merge(['a' => [1 => 'b', 4 => 'c']], ['a' => [1 => 'e', 3 => 'd']], true));
- $this->assertEquals(['a' => [1 => 'c', 3 => 'd', 4 => 'b', 5 => 'a']], a::merge(['a' => [1 => 'a', 4 => 'b']], ['a' => [1 => 'c', 3 => 'd', 5 => 'a']], false));
+ $this->assertEquals(['a', 'b', 'c', 'd', 'a'], A::merge([1 => 'a', 4 => 'b'], [1 => 'c', 3 => 'd', 5 => 'a']));
+ $this->assertEquals(['a', 'b', 'c', 'd', 'a'], A::merge([1 => 'a', 4 => 'b'], [1 => 'c', 3 => 'd', 5 => 'a'], true));
+ $this->assertEquals([1 => 'c', 3 => 'd', 4 => 'b', 5 => 'a'], A::merge([1 => 'a', 4 => 'b'], [1 => 'c', 3 => 'd', 5 => 'a'], false));
+ $this->assertEquals(['a' => ['b', 'c', 'e', 'd']], A::merge(['a' => [1 => 'b', 4 => 'c']], ['a' => [1 => 'e', 3 => 'd']], true));
+ $this->assertEquals(['a' => [1 => 'c', 3 => 'd', 4 => 'b', 5 => 'a']], A::merge(['a' => [1 => 'a', 4 => 'b']], ['a' => [1 => 'c', 3 => 'd', 5 => 'a']], false));
// replace feature
$a = [
diff --git a/tests/Toolkit/CollectionTest.php b/tests/Toolkit/CollectionTest.php
index f18c13badb..db213ea61d 100644
--- a/tests/Toolkit/CollectionTest.php
+++ b/tests/Toolkit/CollectionTest.php
@@ -19,15 +19,18 @@ public function __toString()
class CollectionTest extends TestCase
{
+ protected $collection;
+ protected $sampleData;
+
public function setUp(): void
{
- $this->data = [
+ $this->sampleData = [
'first' => 'My first element',
'second' => 'My second element',
'third' => 'My third element',
];
- $this->collection = new Collection($this->data);
+ $this->collection = new Collection($this->sampleData);
}
public function test__debuginfo()
@@ -39,7 +42,7 @@ public function test__debuginfo()
public function assertIsUntouched()
{
// the original collection must to be untouched
- $this->assertEquals($this->data, $this->collection->toArray());
+ $this->assertEquals($this->sampleData, $this->collection->toArray());
}
public function testAppend()
@@ -99,8 +102,8 @@ public function testFirst()
public function testFlip()
{
- $this->assertEquals(array_reverse($this->data, true), $this->collection->flip()->toArray());
- $this->assertEquals($this->data, $this->collection->flip()->flip()->toArray());
+ $this->assertEquals(array_reverse($this->sampleData, true), $this->collection->flip()->toArray());
+ $this->assertEquals($this->sampleData, $this->collection->flip()->flip()->toArray());
$this->assertIsUntouched();
}
@@ -294,6 +297,83 @@ public function testIndexOf()
$this->assertEquals(1, $this->collection->indexOf('My second element'));
}
+ public function testIntersection()
+ {
+ $collection1 = new Collection([
+ 'a' => $a = new StringObject('a'),
+ 'b' => $b = new StringObject('b'),
+ 'c' => $c = new StringObject('c')
+ ]);
+
+ $collection2 = new Collection([
+ 'c' => $c,
+ 'd' => $d = new StringObject('d'),
+ 'b' => $b
+ ]);
+
+ $collection3 = new Collection([
+ 'd' => $d,
+ 'e' => $e = new StringObject('e')
+ ]);
+
+ // 1 with 2
+ $result = $collection1->intersection($collection2);
+
+ $this->assertCount(2, $result);
+ $this->assertEquals($b, $result->first());
+ $this->assertEquals($c, $result->last());
+
+ // 2 with 1
+ $result = $collection2->intersection($collection1);
+
+ $this->assertCount(2, $result);
+ $this->assertEquals($c, $result->first());
+ $this->assertEquals($b, $result->last());
+
+ // 1 with 3
+ $result = $collection1->intersection($collection3);
+
+ $this->assertCount(0, $result);
+
+ // 3 with 2
+ $result = $collection3->intersection($collection2);
+
+ $this->assertCount(1, $result);
+ $this->assertEquals($d, $result->first());
+ }
+
+ public function testIntersects()
+ {
+ $collection1 = new Collection([
+ 'a' => $a = new StringObject('a'),
+ 'b' => $b = new StringObject('b'),
+ 'c' => $c = new StringObject('c')
+ ]);
+
+ $collection2 = new Collection([
+ 'c' => $c,
+ 'd' => $d = new StringObject('d'),
+ 'b' => $b
+ ]);
+
+ $collection3 = new Collection([
+ 'd' => $d,
+ 'e' => $e = new StringObject('e')
+ ]);
+
+ // 1 with 2
+ $this->assertTrue($collection1->intersects($collection2));
+
+ // 2 with 1
+ $this->assertTrue($collection2->intersects($collection1));
+
+ // 1 with 3
+ $this->assertFalse($collection1->intersects($collection3));
+
+ // 3 with 2
+ $this->assertTrue($collection3->intersects($collection2));
+ }
+
public function testIsEmpty()
{
$collection = new Collection([
@@ -384,9 +464,9 @@ public function testNth()
public function testOffsetAndLimit()
{
- $this->assertEquals(array_slice($this->data, 1), $this->collection->offset(1)->toArray());
- $this->assertEquals(array_slice($this->data, 0, 1), $this->collection->limit(1)->toArray());
- $this->assertEquals(array_slice($this->data, 1, 1), $this->collection->offset(1)->limit(1)->toArray());
+ $this->assertEquals(array_slice($this->sampleData, 1), $this->collection->offset(1)->toArray());
+ $this->assertEquals(array_slice($this->sampleData, 0, 1), $this->collection->limit(1)->toArray());
+ $this->assertEquals(array_slice($this->sampleData, 1, 1), $this->collection->offset(1)->limit(1)->toArray());
$this->assertIsUntouched();
}
@@ -503,6 +583,23 @@ public function testQuerySortBy()
])->first()['name']);
}
+ public function testRemoveMultiple()
+ {
+ $collection = new Collection();
+
+ $collection->set('a', 'A');
+ $collection->set('b', 'B');
+ $collection->set('c', 'C');
+
+ $this->assertCount(3, $collection);
+
+ foreach ($collection as $key => $item) {
+ $collection->__unset($key);
+ }
+
+ $this->assertCount(0, $collection);
+ }
+
public function testSetters()
{
$this->collection->fourth = 'My fourth element';
@@ -526,9 +623,9 @@ public function testShuffle()
public function testSlice()
{
- $this->assertEquals(array_slice($this->data, 1), $this->collection->slice(1)->toArray());
+ $this->assertEquals(array_slice($this->sampleData, 1), $this->collection->slice(1)->toArray());
$this->assertEquals(2, $this->collection->slice(1)->count());
- $this->assertEquals(array_slice($this->data, 0, 1), $this->collection->slice(0, 1)->toArray());
+ $this->assertEquals(array_slice($this->sampleData, 0, 1), $this->collection->slice(0, 1)->toArray());
$this->assertEquals(1, $this->collection->slice(0, 1)->count());
$this->assertIsUntouched();
}
@@ -543,4 +640,75 @@ public function testToArray()
$collection = new Collection($input = ['a', 'b', 'c']);
$this->assertEquals($input, $collection->toArray());
}
+
+ public function testWhen()
+ {
+ $collection = new Collection([
+ [
+ 'name' => 'Bastian',
+ 'color' => 'blue'
+ ],
+ [
+ 'name' => 'Nico',
+ 'color' => 'green'
+ ],
+ [
+ 'name' => 'Lukas',
+ 'color' => 'yellow'
+ ],
+ [
+ 'name' => 'Sonja',
+ 'color' => 'red'
+ ]
+ ]);
+
+ $phpunit = $this;
+ $expectedCondition = null;
+
+ $callback = function ($condition) use ($phpunit, &$expectedCondition) {
+ $phpunit->assertSame($expectedCondition, $condition);
+ return $this->sortBy('name', 'asc');
+ };
+
+ $fallback = function ($condition) use ($phpunit, &$expectedCondition) {
+ $phpunit->assertSame($expectedCondition, $condition);
+ return $this->sortBy('name', 'desc');
+ };
+
+ $sorted = $collection->when($expectedCondition = true, $callback);
+ $this->assertSame('Bastian', $sorted->nth(0)['name']);
+ $this->assertSame('Lukas', $sorted->nth(1)['name']);
+ $this->assertSame('Nico', $sorted->nth(2)['name']);
+ $this->assertSame('Sonja', $sorted->nth(3)['name']);
+
+ $sorted = $collection->when($expectedCondition = 'this is truthy', $callback);
+ $this->assertSame('Bastian', $sorted->nth(0)['name']);
+ $this->assertSame('Lukas', $sorted->nth(1)['name']);
+ $this->assertSame('Nico', $sorted->nth(2)['name']);
+ $this->assertSame('Sonja', $sorted->nth(3)['name']);
+
+ $sorted = $collection->when($expectedCondition = true, $callback, $fallback);
+ $this->assertSame('Bastian', $sorted->nth(0)['name']);
+ $this->assertSame('Lukas', $sorted->nth(1)['name']);
+ $this->assertSame('Nico', $sorted->nth(2)['name']);
+ $this->assertSame('Sonja', $sorted->nth(3)['name']);
+
+ $sorted = $collection->when($expectedCondition = false, $callback);
+ $this->assertSame('Bastian', $sorted->nth(0)['name']);
+ $this->assertSame('Nico', $sorted->nth(1)['name']);
+ $this->assertSame('Lukas', $sorted->nth(2)['name']);
+ $this->assertSame('Sonja', $sorted->nth(3)['name']);
+
+ $sorted = $collection->when($expectedCondition = false, $callback, $fallback);
+ $this->assertSame('Sonja', $sorted->nth(0)['name']);
+ $this->assertSame('Nico', $sorted->nth(1)['name']);
+ $this->assertSame('Lukas', $sorted->nth(2)['name']);
+ $this->assertSame('Bastian', $sorted->nth(3)['name']);
+
+ $sorted = $collection->when($expectedCondition = null, $callback, $fallback);
+ $this->assertSame('Sonja', $sorted->nth(0)['name']);
+ $this->assertSame('Nico', $sorted->nth(1)['name']);
+ $this->assertSame('Lukas', $sorted->nth(2)['name']);
+ $this->assertSame('Bastian', $sorted->nth(3)['name']);
+ }
}
diff --git a/tests/Toolkit/EscapeTest.php b/tests/Toolkit/EscapeTest.php
index 21d0a1a332..0458e77bf8 100644
--- a/tests/Toolkit/EscapeTest.php
+++ b/tests/Toolkit/EscapeTest.php
@@ -29,10 +29,6 @@ class EscapeTest extends TestCase
protected $htmlAttrSpecialChars = [
'\'' => ''',
- '"' => '"',
- '<' => '<',
- '>' => '>',
- '&' => '&',
// Characters beyond ASCII value 255 to unicode escape
'Ā' => 'Ā',
// Characters beyond Unicode BMP to unicode escape
diff --git a/tests/Toolkit/FTest.php b/tests/Toolkit/FTest.php
index 66769af505..0c68f18d51 100644
--- a/tests/Toolkit/FTest.php
+++ b/tests/Toolkit/FTest.php
@@ -4,6 +4,10 @@
class FTest extends TestCase
{
+ protected $fixtures;
+ protected $moved;
+ protected $tmp;
+
public function setUp(): void
{
$this->fixtures = __DIR__ . '/fixtures/f';
diff --git a/tests/Toolkit/FileTest.php b/tests/Toolkit/FileTest.php
index ea2f7173c6..6172c9ab49 100644
--- a/tests/Toolkit/FileTest.php
+++ b/tests/Toolkit/FileTest.php
@@ -2,33 +2,7 @@
namespace Kirby\Toolkit;
-function blockMethod($method, $args)
-{
- if (in_array($method, FileTest::$block)) {
- return false;
- }
- return call_user_func_array('\\' . $method, $args);
-}
-
-function file_put_contents($file, $content)
-{
- return blockMethod('file_put_contents', [$file, $content]);
-}
-
-function rename($old, $new)
-{
- return blockMethod('rename', [$old, $new]);
-}
-
-function copy($old, $new)
-{
- return blockMethod('copy', [$old, $new]);
-}
-
-function unlink($file)
-{
- return blockMethod('unlink', [$file]);
-}
+require_once __DIR__ . '/mocks.php';
class FileTest extends TestCase
{
diff --git a/tests/Toolkit/MimeTest.php b/tests/Toolkit/MimeTest.php
index d27e360202..d348f217a2 100644
--- a/tests/Toolkit/MimeTest.php
+++ b/tests/Toolkit/MimeTest.php
@@ -31,6 +31,33 @@ public function testFromMimeContentType()
$this->assertEquals('text/x-php', $mime);
}
+ public function testIsAccepted()
+ {
+ $pattern = 'text/html,text/plain;q=0.8,application/*;q=0.7';
+
+ $this->assertTrue(Mime::isAccepted('text/html', $pattern));
+ $this->assertTrue(Mime::isAccepted('text/plain', $pattern));
+ $this->assertTrue(Mime::isAccepted('application/json', $pattern));
+ $this->assertTrue(Mime::isAccepted('application/yaml', $pattern));
+
+ $this->assertFalse(Mime::isAccepted('text/xml', $pattern));
+ }
+
+ public function testMatches()
+ {
+ $this->assertTrue(Mime::matches('text/plain', 'text/plain'));
+ $this->assertTrue(Mime::matches('text/plain', 'text/*'));
+ $this->assertTrue(Mime::matches('text/xml', 'text/*'));
+ $this->assertTrue(Mime::matches('text/plain', '*/plain'));
+ $this->assertTrue(Mime::matches('application/plain', '*/plain'));
+ $this->assertTrue(Mime::matches('text/plain', '*/*'));
+ $this->assertTrue(Mime::matches('application/json', '*/*'));
+
+ $this->assertFalse(Mime::matches('text/xml', 'text/plain'));
+ $this->assertFalse(Mime::matches('application/json', 'text/*'));
+ $this->assertFalse(Mime::matches('text/xml', '*/plain'));
+ }
+
public function testToExtension()
{
$extension = Mime::toExtension('image/jpeg');
diff --git a/tests/Toolkit/PaginationTest.php b/tests/Toolkit/PaginationTest.php
index 8261503b7a..22e41ac699 100644
--- a/tests/Toolkit/PaginationTest.php
+++ b/tests/Toolkit/PaginationTest.php
@@ -6,6 +6,11 @@
class PaginationTest extends TestCase
{
+ public function setUp(): void
+ {
+ Pagination::$validate = true;
+ }
+
public function testDefaultPage()
{
$pagination = new Pagination();
@@ -15,75 +20,48 @@ public function testDefaultPage()
$this->assertEquals(1, $pagination->page());
}
- public function testPageSetter()
+ public function testPage()
{
- $pagination = new Pagination();
- $this->assertInstanceOf(Pagination::class, $pagination->page(12));
+ $pagination = new Pagination(['total' => 100, 'page' => 2]);
+ $this->assertEquals(2, $pagination->page());
}
- public function testPageGetter()
+ public function testPageString()
{
- $pagination = new Pagination();
- $pagination->page(12);
- $this->assertEquals(0, $pagination->page());
+ $pagination = new Pagination(['total' => 100, 'page' => '2']);
+ $this->assertEquals(2, $pagination->page());
}
- public function testTotalDefault()
+ public function testPageEmptyCollection()
{
- $pagination = new Pagination();
- $this->assertEquals(0, $pagination->total());
+ $pagination = new Pagination(['total' => 0, 'page' => 1]);
+ $this->assertEquals(0, $pagination->page());
}
- public function testTotalSetter()
+ public function testTotalDefault()
{
$pagination = new Pagination();
- $this->assertInstanceOf(Pagination::class, $pagination->total(12));
+ $this->assertEquals(0, $pagination->total());
}
- public function testTotalGetter()
+ public function testTotal()
{
- $pagination = new Pagination();
- $pagination->total(12);
+ $pagination = new Pagination(['total' => 12]);
$this->assertEquals(12, $pagination->total());
}
- public function testTotalInvalid()
- {
- $this->expectException('Exception');
- $this->expectExceptionMessage('Invalid total number of items: -1');
-
- $pagination = new Pagination();
- $pagination->total(-1);
- }
-
public function testLimitDefault()
{
$pagination = new Pagination();
$this->assertEquals(20, $pagination->limit());
}
- public function testLimitSetter()
- {
- $pagination = new Pagination();
- $this->assertInstanceOf(Pagination::class, $pagination->limit(100));
- }
-
- public function testLimitGetter()
+ public function testLimit()
{
- $pagination = new Pagination();
- $pagination->limit(100);
+ $pagination = new Pagination(['limit' => 100]);
$this->assertEquals(100, $pagination->limit());
}
- public function testLimitInvalid()
- {
- $this->expectException('Exception');
- $this->expectExceptionMessage('Invalid pagination limit: -1');
-
- $pagination = new Pagination();
- $pagination->limit(-1);
- }
-
public function testStart()
{
$pagination = new Pagination([
@@ -93,11 +71,11 @@ public function testStart()
$this->assertEquals(1, $pagination->start());
// go to the second page
- $pagination->page(2);
+ $pagination = $pagination->clone(['page' => 2]);
$this->assertEquals(21, $pagination->start());
// set a different limit
- $pagination->limit(10);
+ $pagination = $pagination->clone(['limit' => 10]);
$this->assertEquals(11, $pagination->start());
}
@@ -110,11 +88,11 @@ public function testEnd()
$this->assertEquals(20, $pagination->end());
// go to the second page
- $pagination->page(2);
+ $pagination = $pagination->clone(['page' => 2]);
$this->assertEquals(40, $pagination->end());
// set a different limit
- $pagination->limit(10);
+ $pagination = $pagination->clone(['limit' => 10]);
$this->assertEquals(20, $pagination->end());
}
@@ -222,7 +200,7 @@ public function testPrevPage()
$pagination = new Pagination(['page' => 2, 'total' => 42]);
$this->assertEquals(1, $pagination->prevPage());
- $pagination = new Pagination(['page' => 1]);
+ $pagination = new Pagination(['page' => 1, 'total' => 42]);
$this->assertEquals(null, $pagination->prevPage());
}
@@ -231,7 +209,7 @@ public function testHasNextPage()
$pagination = new Pagination();
$this->assertFalse($pagination->hasNextPage());
- $pagination = new Pagination(['total' => 42, 'page' => 5]);
+ $pagination = new Pagination(['total' => 42, 'page' => 3]);
$this->assertFalse($pagination->hasNextPage());
$pagination = new Pagination(['total' => 42, 'page' => 2]);
@@ -243,7 +221,7 @@ public function testNextPage()
$pagination = new Pagination(['page' => 1, 'total' => 30]);
$this->assertEquals(2, $pagination->nextPage());
- $pagination = new Pagination(['page' => 3]);
+ $pagination = new Pagination(['page' => 2, 'total' => 30]);
$this->assertEquals(null, $pagination->nextPage());
}
@@ -322,6 +300,85 @@ public function testRange()
$this->assertEquals(10, $pagination->rangeEnd(12));
}
+ public function testClone()
+ {
+ $pagination = new Pagination();
+ $pagination = $pagination->clone(['limit' => 3, 'total' => 5, 'page' => 2]);
+
+ $this->assertSame(3, $pagination->limit());
+ $this->assertSame(5, $pagination->total());
+ $this->assertSame(2, $pagination->page());
+ }
+
+ public function testCloneInvalid1()
+ {
+ $this->expectException('Kirby\Exception\Exception');
+ $this->expectExceptionMessage('Invalid pagination limit: 0');
+
+ $pagination = new Pagination();
+ $pagination = $pagination->clone(['limit' => 0]);
+ }
+
+ public function testCloneInvalid2()
+ {
+ $this->expectException('Kirby\Exception\Exception');
+ $this->expectExceptionMessage('Invalid total number of items: -1');
+
+ $pagination = new Pagination();
+ $pagination = $pagination->clone(['total' => -1]);
+ }
+
+ public function testCloneInvalid3()
+ {
+ $this->expectException('Kirby\Exception\Exception');
+ $this->expectExceptionMessage('Invalid page number: -1');
+
+ $pagination = new Pagination();
+ $pagination = $pagination->clone(['page' => -1]);
+ }
+
+ public function testCloneOutOfBounds1()
+ {
+ $this->expectException('Kirby\Exception\ErrorPageException');
+ $this->expectExceptionMessage('Pagination page 3 does not exist, expected 1-2');
+
+ $pagination = new Pagination();
+ $pagination = $pagination->clone(['page' => 3, 'total' => 10, 'limit' => 5]);
+ }
+
+ public function testCloneOutOfBounds2()
+ {
+ $this->expectException('Kirby\Exception\ErrorPageException');
+ $this->expectExceptionMessage('Pagination page 0 does not exist, expected 1-2');
+
+ $pagination = new Pagination();
+ $pagination = $pagination->clone(['page' => 0, 'total' => 10, 'limit' => 5]);
+ }
+
+ public function testCloneOutOfBoundsNoValidate1()
+ {
+ Pagination::$validate = false;
+
+ $pagination = new Pagination();
+ $pagination = $pagination->clone(['page' => 3, 'total' => 10, 'limit' => 5]);
+
+ $this->assertSame(2, $pagination->page());
+
+ Pagination::$validate = true;
+ }
+
+ public function testCloneOutOfBoundsNoValidate2()
+ {
+ Pagination::$validate = false;
+
+ $pagination = new Pagination();
+ $pagination = $pagination->clone(['page' => 0, 'total' => 10, 'limit' => 5]);
+
+ $this->assertSame(1, $pagination->page());
+
+ Pagination::$validate = true;
+ }
+
public function testToArray()
{
$pagination = new Pagination();
diff --git a/tests/Toolkit/VTest.php b/tests/Toolkit/VTest.php
index f55d1641b1..20bab8758e 100644
--- a/tests/Toolkit/VTest.php
+++ b/tests/Toolkit/VTest.php
@@ -356,7 +356,7 @@ public function testSizeInvalidObject()
$this->expectException('Exception');
$this->expectExceptionMessage('$value is an uncountable object');
- V::size(new \StdClass(), 5);
+ V::size(new \stdClass(), 5);
}
public function testTime()
@@ -371,6 +371,8 @@ public function testUrl()
$this->assertTrue(V::url('http://www.getkirby.com'));
$this->assertTrue(V::url('http://www.getkirby.com/docs/param:value/?foo=bar/#anchor'));
$this->assertTrue(V::url('https://www.getkirby.de.vu'));
+ $this->assertTrue(V::url('https://getkirby.com:1234'));
+ $this->assertTrue(V::url('https://getkirby.com:1234/test'));
$this->assertTrue(V::url('http://foo.com/blah_blah'));
$this->assertTrue(V::url('http://foo.com/blah_blah/'));
$this->assertTrue(V::url('http://foo.com/blah_blah_(wikipedia)'));
@@ -407,10 +409,17 @@ public function testUrl()
$this->assertTrue(V::url('http://1337.net'));
$this->assertTrue(V::url('http://a.b-c.de'));
$this->assertTrue(V::url('http://223.255.255.254'));
+ $this->assertTrue(V::url('http://localhost/test/'));
+ $this->assertTrue(V::url('http://localhost:8080/test'));
+ $this->assertTrue(V::url('http://127.0.0.1/kirby/'));
+ $this->assertTrue(V::url('http://127.0.0.1:8080/kirby'));
+ $this->assertTrue(V::url('https://127.0.0.1/kirby/panel/pages/blog+vvvv'));
+ $this->assertTrue(V::url('https://localhost/kirby/panel/pages/blog+vvvv'));
+
// TODO: Find better regex to also cover the following
// $this->assertTrue(V::url('http://special---offer.com/'));
- // $this->assertTrue(V::url('http://localhost/test/'));
- // $this->assertTrue(V::url('http://localhost:8080/test'));
+ // $this->assertTrue(V::url('http://10.1.1.1'));
+ // $this->assertTrue(V::url('http://10.1.1.254'));
$this->assertFalse(V::url('foo'));
$this->assertFalse(V::url('http://'));
@@ -450,8 +459,6 @@ public function testUrl()
$this->assertFalse(V::url('http://.www.foo.bar/'));
$this->assertFalse(V::url('http://www.foo.bar./'));
$this->assertFalse(V::url('http://.www.foo.bar./'));
- $this->assertFalse(V::url('http://10.1.1.1'));
- $this->assertFalse(V::url('http://10.1.1.254'));
}
public function inputProvider()
diff --git a/tests/Toolkit/mocks.php b/tests/Toolkit/mocks.php
new file mode 100644
index 0000000000..fd5d284a8e
--- /dev/null
+++ b/tests/Toolkit/mocks.php
@@ -0,0 +1,31 @@
+ $baseDir . '/src/Cache/Cache.php',
'Kirby\\Cache\\FileCache' => $baseDir . '/src/Cache/FileCache.php',
'Kirby\\Cache\\MemCached' => $baseDir . '/src/Cache/MemCached.php',
+ 'Kirby\\Cache\\MemoryCache' => $baseDir . '/src/Cache/MemoryCache.php',
+ 'Kirby\\Cache\\NullCache' => $baseDir . '/src/Cache/NullCache.php',
'Kirby\\Cache\\Value' => $baseDir . '/src/Cache/Value.php',
'Kirby\\Cms\\Api' => $baseDir . '/src/Cms/Api.php',
'Kirby\\Cms\\App' => $baseDir . '/src/Cms/App.php',
@@ -27,6 +29,8 @@
'Kirby\\Cms\\Collection' => $baseDir . '/src/Cms/Collection.php',
'Kirby\\Cms\\Collections' => $baseDir . '/src/Cms/Collections.php',
'Kirby\\Cms\\Content' => $baseDir . '/src/Cms/Content.php',
+ 'Kirby\\Cms\\ContentLock' => $baseDir . '/src/Cms/ContentLock.php',
+ 'Kirby\\Cms\\ContentLocks' => $baseDir . '/src/Cms/ContentLocks.php',
'Kirby\\Cms\\ContentTranslation' => $baseDir . '/src/Cms/ContentTranslation.php',
'Kirby\\Cms\\Dir' => $baseDir . '/src/Cms/Dir.php',
'Kirby\\Cms\\Email' => $baseDir . '/src/Cms/Email.php',
@@ -37,6 +41,7 @@
'Kirby\\Cms\\FileFoundation' => $baseDir . '/src/Cms/FileFoundation.php',
'Kirby\\Cms\\FileModifications' => $baseDir . '/src/Cms/FileModifications.php',
'Kirby\\Cms\\FilePermissions' => $baseDir . '/src/Cms/FilePermissions.php',
+ 'Kirby\\Cms\\FilePicker' => $baseDir . '/src/Cms/FilePicker.php',
'Kirby\\Cms\\FileRules' => $baseDir . '/src/Cms/FileRules.php',
'Kirby\\Cms\\FileVersion' => $baseDir . '/src/Cms/FileVersion.php',
'Kirby\\Cms\\Filename' => $baseDir . '/src/Cms/Filename.php',
@@ -51,6 +56,9 @@
'Kirby\\Cms\\KirbyTag' => $baseDir . '/src/Cms/KirbyTag.php',
'Kirby\\Cms\\KirbyTags' => $baseDir . '/src/Cms/KirbyTags.php',
'Kirby\\Cms\\Language' => $baseDir . '/src/Cms/Language.php',
+ 'Kirby\\Cms\\LanguageRouter' => $baseDir . '/src/Cms/LanguageRouter.php',
+ 'Kirby\\Cms\\LanguageRoutes' => $baseDir . '/src/Cms/LanguageRoutes.php',
+ 'Kirby\\Cms\\LanguageRules' => $baseDir . '/src/Cms/LanguageRules.php',
'Kirby\\Cms\\Languages' => $baseDir . '/src/Cms/Languages.php',
'Kirby\\Cms\\Media' => $baseDir . '/src/Cms/Media.php',
'Kirby\\Cms\\Model' => $baseDir . '/src/Cms/Model.php',
@@ -63,6 +71,7 @@
'Kirby\\Cms\\PageActions' => $baseDir . '/src/Cms/PageActions.php',
'Kirby\\Cms\\PageBlueprint' => $baseDir . '/src/Cms/PageBlueprint.php',
'Kirby\\Cms\\PagePermissions' => $baseDir . '/src/Cms/PagePermissions.php',
+ 'Kirby\\Cms\\PagePicker' => $baseDir . '/src/Cms/PagePicker.php',
'Kirby\\Cms\\PageRules' => $baseDir . '/src/Cms/PageRules.php',
'Kirby\\Cms\\PageSiblings' => $baseDir . '/src/Cms/PageSiblings.php',
'Kirby\\Cms\\Pages' => $baseDir . '/src/Cms/Pages.php',
@@ -70,6 +79,7 @@
'Kirby\\Cms\\Panel' => $baseDir . '/src/Cms/Panel.php',
'Kirby\\Cms\\PanelPlugins' => $baseDir . '/src/Cms/PanelPlugins.php',
'Kirby\\Cms\\Permissions' => $baseDir . '/src/Cms/Permissions.php',
+ 'Kirby\\Cms\\Picker' => $baseDir . '/src/Cms/Picker.php',
'Kirby\\Cms\\Plugin' => $baseDir . '/src/Cms/Plugin.php',
'Kirby\\Cms\\PluginAssets' => $baseDir . '/src/Cms/PluginAssets.php',
'Kirby\\Cms\\R' => $baseDir . '/src/Cms/R.php',
@@ -96,6 +106,7 @@
'Kirby\\Cms\\UserActions' => $baseDir . '/src/Cms/UserActions.php',
'Kirby\\Cms\\UserBlueprint' => $baseDir . '/src/Cms/UserBlueprint.php',
'Kirby\\Cms\\UserPermissions' => $baseDir . '/src/Cms/UserPermissions.php',
+ 'Kirby\\Cms\\UserPicker' => $baseDir . '/src/Cms/UserPicker.php',
'Kirby\\Cms\\UserRules' => $baseDir . '/src/Cms/UserRules.php',
'Kirby\\Cms\\Users' => $baseDir . '/src/Cms/Users.php',
'Kirby\\Cms\\Visitor' => $baseDir . '/src/Cms/Visitor.php',
@@ -120,6 +131,7 @@
'Kirby\\Email\\PHPMailer' => $baseDir . '/src/Email/PHPMailer.php',
'Kirby\\Exception\\BadMethodCallException' => $baseDir . '/src/Exception/BadMethodCallException.php',
'Kirby\\Exception\\DuplicateException' => $baseDir . '/src/Exception/DuplicateException.php',
+ 'Kirby\\Exception\\ErrorPageException' => $baseDir . '/src/Exception/ErrorPageException.php',
'Kirby\\Exception\\Exception' => $baseDir . '/src/Exception/Exception.php',
'Kirby\\Exception\\InvalidArgumentException' => $baseDir . '/src/Exception/InvalidArgumentException.php',
'Kirby\\Exception\\LogicException' => $baseDir . '/src/Exception/LogicException.php',
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 70e3b83a9e..a724e24b90 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -101,6 +101,8 @@ class ComposerStaticInit12091bebabd81c9aba88b2aeec22c8d7
'Kirby\\Cache\\Cache' => __DIR__ . '/../..' . '/src/Cache/Cache.php',
'Kirby\\Cache\\FileCache' => __DIR__ . '/../..' . '/src/Cache/FileCache.php',
'Kirby\\Cache\\MemCached' => __DIR__ . '/../..' . '/src/Cache/MemCached.php',
+ 'Kirby\\Cache\\MemoryCache' => __DIR__ . '/../..' . '/src/Cache/MemoryCache.php',
+ 'Kirby\\Cache\\NullCache' => __DIR__ . '/../..' . '/src/Cache/NullCache.php',
'Kirby\\Cache\\Value' => __DIR__ . '/../..' . '/src/Cache/Value.php',
'Kirby\\Cms\\Api' => __DIR__ . '/../..' . '/src/Cms/Api.php',
'Kirby\\Cms\\App' => __DIR__ . '/../..' . '/src/Cms/App.php',
@@ -115,6 +117,8 @@ class ComposerStaticInit12091bebabd81c9aba88b2aeec22c8d7
'Kirby\\Cms\\Collection' => __DIR__ . '/../..' . '/src/Cms/Collection.php',
'Kirby\\Cms\\Collections' => __DIR__ . '/../..' . '/src/Cms/Collections.php',
'Kirby\\Cms\\Content' => __DIR__ . '/../..' . '/src/Cms/Content.php',
+ 'Kirby\\Cms\\ContentLock' => __DIR__ . '/../..' . '/src/Cms/ContentLock.php',
+ 'Kirby\\Cms\\ContentLocks' => __DIR__ . '/../..' . '/src/Cms/ContentLocks.php',
'Kirby\\Cms\\ContentTranslation' => __DIR__ . '/../..' . '/src/Cms/ContentTranslation.php',
'Kirby\\Cms\\Dir' => __DIR__ . '/../..' . '/src/Cms/Dir.php',
'Kirby\\Cms\\Email' => __DIR__ . '/../..' . '/src/Cms/Email.php',
@@ -125,6 +129,7 @@ class ComposerStaticInit12091bebabd81c9aba88b2aeec22c8d7
'Kirby\\Cms\\FileFoundation' => __DIR__ . '/../..' . '/src/Cms/FileFoundation.php',
'Kirby\\Cms\\FileModifications' => __DIR__ . '/../..' . '/src/Cms/FileModifications.php',
'Kirby\\Cms\\FilePermissions' => __DIR__ . '/../..' . '/src/Cms/FilePermissions.php',
+ 'Kirby\\Cms\\FilePicker' => __DIR__ . '/../..' . '/src/Cms/FilePicker.php',
'Kirby\\Cms\\FileRules' => __DIR__ . '/../..' . '/src/Cms/FileRules.php',
'Kirby\\Cms\\FileVersion' => __DIR__ . '/../..' . '/src/Cms/FileVersion.php',
'Kirby\\Cms\\Filename' => __DIR__ . '/../..' . '/src/Cms/Filename.php',
@@ -139,6 +144,9 @@ class ComposerStaticInit12091bebabd81c9aba88b2aeec22c8d7
'Kirby\\Cms\\KirbyTag' => __DIR__ . '/../..' . '/src/Cms/KirbyTag.php',
'Kirby\\Cms\\KirbyTags' => __DIR__ . '/../..' . '/src/Cms/KirbyTags.php',
'Kirby\\Cms\\Language' => __DIR__ . '/../..' . '/src/Cms/Language.php',
+ 'Kirby\\Cms\\LanguageRouter' => __DIR__ . '/../..' . '/src/Cms/LanguageRouter.php',
+ 'Kirby\\Cms\\LanguageRoutes' => __DIR__ . '/../..' . '/src/Cms/LanguageRoutes.php',
+ 'Kirby\\Cms\\LanguageRules' => __DIR__ . '/../..' . '/src/Cms/LanguageRules.php',
'Kirby\\Cms\\Languages' => __DIR__ . '/../..' . '/src/Cms/Languages.php',
'Kirby\\Cms\\Media' => __DIR__ . '/../..' . '/src/Cms/Media.php',
'Kirby\\Cms\\Model' => __DIR__ . '/../..' . '/src/Cms/Model.php',
@@ -151,6 +159,7 @@ class ComposerStaticInit12091bebabd81c9aba88b2aeec22c8d7
'Kirby\\Cms\\PageActions' => __DIR__ . '/../..' . '/src/Cms/PageActions.php',
'Kirby\\Cms\\PageBlueprint' => __DIR__ . '/../..' . '/src/Cms/PageBlueprint.php',
'Kirby\\Cms\\PagePermissions' => __DIR__ . '/../..' . '/src/Cms/PagePermissions.php',
+ 'Kirby\\Cms\\PagePicker' => __DIR__ . '/../..' . '/src/Cms/PagePicker.php',
'Kirby\\Cms\\PageRules' => __DIR__ . '/../..' . '/src/Cms/PageRules.php',
'Kirby\\Cms\\PageSiblings' => __DIR__ . '/../..' . '/src/Cms/PageSiblings.php',
'Kirby\\Cms\\Pages' => __DIR__ . '/../..' . '/src/Cms/Pages.php',
@@ -158,6 +167,7 @@ class ComposerStaticInit12091bebabd81c9aba88b2aeec22c8d7
'Kirby\\Cms\\Panel' => __DIR__ . '/../..' . '/src/Cms/Panel.php',
'Kirby\\Cms\\PanelPlugins' => __DIR__ . '/../..' . '/src/Cms/PanelPlugins.php',
'Kirby\\Cms\\Permissions' => __DIR__ . '/../..' . '/src/Cms/Permissions.php',
+ 'Kirby\\Cms\\Picker' => __DIR__ . '/../..' . '/src/Cms/Picker.php',
'Kirby\\Cms\\Plugin' => __DIR__ . '/../..' . '/src/Cms/Plugin.php',
'Kirby\\Cms\\PluginAssets' => __DIR__ . '/../..' . '/src/Cms/PluginAssets.php',
'Kirby\\Cms\\R' => __DIR__ . '/../..' . '/src/Cms/R.php',
@@ -184,6 +194,7 @@ class ComposerStaticInit12091bebabd81c9aba88b2aeec22c8d7
'Kirby\\Cms\\UserActions' => __DIR__ . '/../..' . '/src/Cms/UserActions.php',
'Kirby\\Cms\\UserBlueprint' => __DIR__ . '/../..' . '/src/Cms/UserBlueprint.php',
'Kirby\\Cms\\UserPermissions' => __DIR__ . '/../..' . '/src/Cms/UserPermissions.php',
+ 'Kirby\\Cms\\UserPicker' => __DIR__ . '/../..' . '/src/Cms/UserPicker.php',
'Kirby\\Cms\\UserRules' => __DIR__ . '/../..' . '/src/Cms/UserRules.php',
'Kirby\\Cms\\Users' => __DIR__ . '/../..' . '/src/Cms/Users.php',
'Kirby\\Cms\\Visitor' => __DIR__ . '/../..' . '/src/Cms/Visitor.php',
@@ -208,6 +219,7 @@ class ComposerStaticInit12091bebabd81c9aba88b2aeec22c8d7
'Kirby\\Email\\PHPMailer' => __DIR__ . '/../..' . '/src/Email/PHPMailer.php',
'Kirby\\Exception\\BadMethodCallException' => __DIR__ . '/../..' . '/src/Exception/BadMethodCallException.php',
'Kirby\\Exception\\DuplicateException' => __DIR__ . '/../..' . '/src/Exception/DuplicateException.php',
+ 'Kirby\\Exception\\ErrorPageException' => __DIR__ . '/../..' . '/src/Exception/ErrorPageException.php',
'Kirby\\Exception\\Exception' => __DIR__ . '/../..' . '/src/Exception/Exception.php',
'Kirby\\Exception\\InvalidArgumentException' => __DIR__ . '/../..' . '/src/Exception/InvalidArgumentException.php',
'Kirby\\Exception\\LogicException' => __DIR__ . '/../..' . '/src/Exception/LogicException.php',
diff --git a/vendor/psr/log/Psr/Log/LoggerInterface.php b/vendor/psr/log/Psr/Log/LoggerInterface.php
index 5ea72438b5..e695046e30 100644
--- a/vendor/psr/log/Psr/Log/LoggerInterface.php
+++ b/vendor/psr/log/Psr/Log/LoggerInterface.php
@@ -118,6 +118,8 @@ public function debug($message, array $context = array());
* @param array $context
*
* @return void
+ *
+ * @throws \Psr\Log\InvalidArgumentException
*/
public function log($level, $message, array $context = array());
}
diff --git a/vendor/psr/log/Psr/Log/LoggerTrait.php b/vendor/psr/log/Psr/Log/LoggerTrait.php
index 867225df1d..e392fef0a0 100644
--- a/vendor/psr/log/Psr/Log/LoggerTrait.php
+++ b/vendor/psr/log/Psr/Log/LoggerTrait.php
@@ -135,6 +135,8 @@ public function debug($message, array $context = array())
* @param array $context
*
* @return void
+ *
+ * @throws \Psr\Log\InvalidArgumentException
*/
abstract public function log($level, $message, array $context = array());
}
diff --git a/vendor/psr/log/Psr/Log/NullLogger.php b/vendor/psr/log/Psr/Log/NullLogger.php
index d8cd682c8f..c8f7293b1c 100644
--- a/vendor/psr/log/Psr/Log/NullLogger.php
+++ b/vendor/psr/log/Psr/Log/NullLogger.php
@@ -20,6 +20,8 @@ class NullLogger extends AbstractLogger
* @param array $context
*
* @return void
+ *
+ * @throws \Psr\Log\InvalidArgumentException
*/
public function log($level, $message, array $context = array())
{
diff --git a/vendor/symfony/polyfill-mbstring/Mbstring.php b/vendor/symfony/polyfill-mbstring/Mbstring.php
index a5e4a8fde4..1fc4feea72 100644
--- a/vendor/symfony/polyfill-mbstring/Mbstring.php
+++ b/vendor/symfony/polyfill-mbstring/Mbstring.php
@@ -35,6 +35,7 @@
* - mb_strlen - Get string length
* - mb_strpos - Find position of first occurrence of string in a string
* - mb_strrpos - Find position of last occurrence of a string in a string
+ * - mb_str_split - Convert a string to an array
* - mb_strtolower - Make a string lowercase
* - mb_strtoupper - Make a string uppercase
* - mb_substitute_character - Set/Get substitution character
@@ -523,6 +524,34 @@ public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = n
return false !== $pos ? $offset + $pos : false;
}
+ public static function mb_str_split($string, $split_length = 1, $encoding = null)
+ {
+ if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) {
+ trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING);
+
+ return null;
+ }
+
+ if ($split_length < 1) {
+ trigger_error('The length of each segment must be greater than zero', E_USER_WARNING);
+
+ return false;
+ }
+
+ if (null === $encoding) {
+ $encoding = mb_internal_encoding();
+ }
+
+ $result = array();
+ $length = mb_strlen($string, $encoding);
+
+ for ($i = 0; $i < $length; $i += $split_length) {
+ $result[] = mb_substr($string, $i, $split_length, $encoding);
+ }
+
+ return $result;
+ }
+
public static function mb_strtolower($s, $encoding = null)
{
return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
@@ -546,7 +575,7 @@ public static function mb_substr($s, $start, $length = null, $encoding = null)
{
$encoding = self::getEncoding($encoding);
if ('CP850' === $encoding || 'ASCII' === $encoding) {
- return substr($s, $start, null === $length ? 2147483647 : $length);
+ return (string) substr($s, $start, null === $length ? 2147483647 : $length);
}
if ($start < 0) {
diff --git a/vendor/symfony/polyfill-mbstring/bootstrap.php b/vendor/symfony/polyfill-mbstring/bootstrap.php
index 2fdcc5a6f6..204a41ba27 100644
--- a/vendor/symfony/polyfill-mbstring/bootstrap.php
+++ b/vendor/symfony/polyfill-mbstring/bootstrap.php
@@ -56,3 +56,7 @@ function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
}
+
+if (!function_exists('mb_str_split')) {
+ function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); }
+}
diff --git a/views/panel.php b/views/panel.php
index 8906c5899c..2663f6e5de 100644
--- a/views/panel.php
+++ b/views/panel.php
@@ -7,20 +7,20 @@
Kirby Panel
-
-
+
+
-
+
-
-
+
+
-