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 `
` tags. + * + * @param \Kirby\Cms\Field $field + * @return \Kirby\Cms\Field + */ + 'nl2br' => function (Field $field) { + $field->value = nl2br($field->value, false); + return $field; + }, + /** * Converts the field content from Markdown/Kirbytext to valid HTML * @@ -372,6 +383,23 @@ return $field; }, + /** + * Strips all block-level HTML elements from the field value, + * it can be safely placed inside of other inline elements + * without the risk of breaking the HTML structure. + * + * @param \Kirby\Cms\Field $field + * @return \Kirby\Cms\Field + */ + 'inline' => function (Field $field) { + // List of valid inline elements taken from: https://developer.mozilla.org/de/docs/Web/HTML/Inline_elemente + // Obsolete elements, script tags, image maps and form elements have + // been excluded for safety reasons and as they are most likely not + // needed in most cases. + $field->value = strip_tags($field->value, '
'); + 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 @@ 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") }} + + 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: \ 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 - - + + - + - - + + -