diff --git a/.github/workflows/subsplit.yml b/.github/workflows/subsplit.yml new file mode 100644 index 0000000000..bc4b3aed71 --- /dev/null +++ b/.github/workflows/subsplit.yml @@ -0,0 +1,27 @@ +name: Module sub-split + +on: + push: + create: + delete: + +jobs: + split: + name: Sub-split + runs-on: ubuntu-latest + container: wintercms/cli:0.3.4 + env: + WINTER_CLI_GITHUB_TOKEN: ${{ secrets.WINTER_SPLIT_TOKEN }} + steps: + - name: Create tag + if: github.event_name == 'create' && github.ref_type == 'tag' + run: winter split -a "${{ github.ref_name }}" + - name: Delete branch + if: github.event_name == 'delete' && github.ref_type == 'branch' + run: winter split --remove-branch="${{ github.event.ref }}" + - name: Delete tag + if: github.event_name == 'delete' && github.ref_type == 'tag' + run: winter split --remove-tag="${{ github.event.ref }}" + - name: Push + if: github.event_name == 'push' + run: winter split -b "${{ github.ref_name }}" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6dfd3f074f..a64cdaff0d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -3,34 +3,96 @@ name: Tests on: push: branches: - - 1.0 - - 1.1 - - 1.2 + - '1.2' - develop pull_request: jobs: frontendTests: - runs-on: ubuntu-latest - name: JavaScript + strategy: + max-parallel: 2 + matrix: + operatingSystem: [ubuntu-latest, windows-latest] + fail-fast: false + runs-on: ${{ matrix.operatingSystem }} + name: ${{ matrix.operatingSystem }} / JavaScript + env: + nodeVersion: 16 + phpVersion: '8.0' + extensions: curl, fileinfo, gd, mbstring, openssl, pdo, pdo_sqlite, sqlite3, xml, zip + key: winter-cms-cache-develop steps: + - name: Cancel previous incomplete runs + uses: styfle/cancel-workflow-action@0.8.0 + with: + access_token: ${{ github.token }} + - name: Checkout changes - uses: actions/checkout@v2 + uses: actions/checkout@v3 + + - name: Setup extension cache + id: extcache + uses: shivammathur/cache-extensions@v1 + with: + php-version: ${{ env.phpVersion }} + extensions: ${{ env.extensions }} + key: ${{ env.key }} + + - name: Cache extensions + uses: actions/cache@v3 with: - fetch-depth: 0 + path: ${{ steps.extcache.outputs.dir }} + key: ${{ steps.extcache.outputs.key }} + restore-keys: ${{ steps.extcache.outputs.key }} + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ env.phpVersion }} + extensions: ${{ env.extensions }} - name: Install Node - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: - node-version: 12 + node-version: ${{ env.nodeVersion }} - - name: Install Node dependencies - working-directory: ./modules/system/tests/js - run: npm install + - name: Echo branches + run: echo "${{ github.ref }} | ${{ github.head_ref }} | ${{ github.ref_name }} | ${{ github.base_ref }}" + + - name: Switch library dependency (develop) + if: github.ref == 'refs/heads/develop' || github.base_ref == 'develop' + run: php ./.github/workflows/utilities/library-switcher "dev-develop as 1.2" + + - name: Switch library dependency (1.2) + if: github.head_ref == '1.2' || github.ref == 'refs/heads/1.2' || github.base_ref == '1.2' + run: php ./.github/workflows/utilities/library-switcher "1.2.x-dev as 1.2" + + - name: Setup dependency cache + id: composercache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composercache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-interaction --no-progress --no-scripts + + - name: Reset modules + run: | + git reset --hard + git clean -fd + + - name: Run post-update Composer scripts + run: php artisan package:discover - name: Run tests - working-directory: ./modules/system/tests/js - run: npm run test + run: | + php artisan mix:install + php artisan mix:run module-system test phpUnitTests: strategy: @@ -108,7 +170,9 @@ jobs: run: composer install --no-interaction --no-progress --no-scripts - name: Reset modules - run: git reset --hard + run: | + git reset --hard + git clean -fd - name: Run post-update Composer scripts run: php artisan package:discover @@ -120,4 +184,4 @@ jobs: - name: Run Linting and Tests run: | composer lint - ./vendor/bin/phpunit + php artisan winter:test -m system -m backend -m cms diff --git a/README.md b/README.md index 1185b210f3..ca0fce5259 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,24 @@ Please follow the following guides and code standards: In order to ensure that the Winter community is welcoming to all, please review and abide by the [Code of Conduct](https://github.com/wintercms/.github/blob/master/CODE_OF_CONDUCT.md). +## Sponsors + +Winter CMS development is financially supported by the generosity of the following sponsors: + +### Organizations + +[![Spatial Media logo](https://cdn.ca.spatialmedia.io/media/images/sm-logo-dark-full.svg)](https://spatialmedia.io) +Spatial Media employs two of the core contributors (Luke Towers & Jack Wilkinson) and contributes to the ongoing development of Winter. + +[![Froala logo](https://froala.com/wp-content/uploads/2019/10/froala.svg)](https://froala.com/wysiwyg-editor/) + +Froala provides a perpetual, Enterprise license to Winter CMS which allows us and our users to use the Froala WYSIWYG Editor in Winter CMS powered projects. + +### Individuals +- Orville + +If you would like to have your name, company and link added to this list and support open-source development, feel free to make a donation to our [Open Collective](https://opencollective.com/wintercms). + ## License The Winter platform is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). diff --git a/composer.json b/composer.json index ad352e7e69..da09aae0e3 100644 --- a/composer.json +++ b/composer.json @@ -68,7 +68,7 @@ "extra": { "merge-plugin": { "include": [ - "plugins/*/*/composer.json" + "plugins/myauthor/*/composer.json" ], "recurse": true, "replace": false, diff --git a/config/app.php b/config/app.php index c4d3537fc2..1520e862cc 100644 --- a/config/app.php +++ b/config/app.php @@ -59,6 +59,19 @@ */ 'asset_url' => env('ASSET_URL', null), + + /* + |-------------------------------------------------------------------------- + | Temporary Path + |-------------------------------------------------------------------------- + | + | This is used to set the application's temporary path. Normally this value + | is set automatically by the application, however on some systems you + | may need to change it (Laravel Vapor / read-only systems: /tmp). + | + */ + + 'tempPath' => env('APP_TEMP_PATH', null), /* |-------------------------------------------------------------------------- @@ -106,14 +119,18 @@ | - array: An array of proxies to trust | | Examples: - | - To trust all proxies: + | - To trust any proxy (i.e. a single proxy with an unknown IP address): + | + | 'trustedProxies' => '*', + | + | - To trust all proxies (i.e. AWS ELB behind CloudFront): | - | 'trustedProxies' => '*' + | 'trustedProxies' => '**', | | - To trust two IP addresses as proxies | - | 'trustedProxies' => '192.168.1.1, 192.168.1.2' - | 'trustedProxies' => ['192.168.1.1', '192.168.1.2'] + | 'trustedProxies' => '192.168.1.1, 192.168.1.2', + | 'trustedProxies' => ['192.168.1.1', '192.168.1.2'], */ 'trustedProxies' => null, diff --git a/config/filesystems.php b/config/filesystems.php index 98904ecd94..64cd1768b6 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -26,6 +26,9 @@ | | Supported Drivers: "local", "ftp", "sftp", "s3" | + | NOTE: s3's stream_uploads option requires the Winter.DriverAWS plugin + | to be installed and enabled. + | */ 'disks' => [ @@ -42,6 +45,7 @@ 'key' => env('AWS_ACCESS_KEY_ID'), 'region' => env('AWS_DEFAULT_REGION'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'stream_uploads' => env('AWS_S3_STREAM_UPLOADS', false), 'url' => env('AWS_URL'), 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), ], diff --git a/modules/backend/LICENSE b/modules/backend/LICENSE new file mode 100644 index 0000000000..7b47a3b139 --- /dev/null +++ b/modules/backend/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2013-2021.03.01 October CMS +Copyright (c) 2021 Winter CMS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/modules/backend/README.md b/modules/backend/README.md new file mode 100644 index 0000000000..bce0dcf1e6 --- /dev/null +++ b/modules/backend/README.md @@ -0,0 +1,5 @@ +# Winter CMS - Backend Module + +This repository is a read-only sub-split of the Winter CMS `Backend` module for use in Composer. Please note that we do not accept any pull requests to this repository. + +If you wish to make changes to this module, please submit them to the [main repository](https://github.com/wintercms/winter). diff --git a/modules/backend/assets/less/controls/filelist.less b/modules/backend/assets/less/controls/filelist.less index 07e4a8ab21..37ba76cb62 100644 --- a/modules/backend/assets/less/controls/filelist.less +++ b/modules/backend/assets/less/controls/filelist.less @@ -284,7 +284,8 @@ .list-icon { position: absolute; left: 14px; - top: 15px; + top: 50%; + transform: translateY(-50%); font-size: 22px; color: #b7c0c2; } diff --git a/modules/backend/behaviors/FormController.php b/modules/backend/behaviors/FormController.php index 28d58c4157..25660de317 100644 --- a/modules/backend/behaviors/FormController.php +++ b/modules/backend/behaviors/FormController.php @@ -33,7 +33,7 @@ * values as either a YAML file, located in the controller view directory, * or directly as a PHP array. * - * @see http://wintercms.com/docs/backend/forms Back-end form documentation + * @see https://wintercms.com/docs/backend/forms Back-end form documentation * @package winter\wn-backend-module * @author Alexey Bobkov, Samuel Georges */ diff --git a/modules/backend/behaviors/ImportExportController.php b/modules/backend/behaviors/ImportExportController.php index d93683dea4..057a0758a3 100644 --- a/modules/backend/behaviors/ImportExportController.php +++ b/modules/backend/behaviors/ImportExportController.php @@ -12,6 +12,7 @@ use League\Csv\Reader as CsvReader; use League\Csv\Writer as CsvWriter; use League\Csv\EscapeFormula as CsvEscapeFormula; +use League\Csv\Statement as CsvStatement; use ApplicationException; use SplTempFileObject; use Exception; @@ -250,10 +251,10 @@ public function onImportLoadColumnSampleForm() $reader = $this->createCsvReader($path); if (post('first_row_titles')) { - $reader->setOffset(1); + $reader->setHeaderOffset(1); } - $result = $reader->setLimit(50)->fetchColumn((int) $columnId); + $result = (new CsvStatement())->limit(50)->process($reader)->fetchColumn((int) $columnId); $data = iterator_to_array($result, false); /* diff --git a/modules/backend/console/WinterPasswd.php b/modules/backend/console/WinterPasswd.php index 25bad1da84..ecaf088067 100644 --- a/modules/backend/console/WinterPasswd.php +++ b/modules/backend/console/WinterPasswd.php @@ -31,6 +31,13 @@ class WinterPasswd extends Command * @var string The console command description. */ protected $description = 'Change the password of a Backend user.'; + + /** + * @var array List of commands that this command replaces (aliases) + */ + protected $replaces = [ + 'winter:password', + ]; /** * @var bool Was the password automatically generated? diff --git a/modules/backend/console/scaffold/controller/create.stub b/modules/backend/console/scaffold/controller/create.stub index e981d2ad82..8836705591 100644 --- a/modules/backend/console/scaffold/controller/create.stub +++ b/modules/backend/console/scaffold/controller/create.stub @@ -16,7 +16,7 @@
+
diff --git a/modules/backend/database/seeds/DatabaseSeeder.php b/modules/backend/database/seeds/DatabaseSeeder.php index f05589c9b6..59210f3d32 100644 --- a/modules/backend/database/seeds/DatabaseSeeder.php +++ b/modules/backend/database/seeds/DatabaseSeeder.php @@ -14,7 +14,7 @@ class DatabaseSeeder extends Seeder */ public function run() { - $shouldRandomizePassword = SeedSetupAdmin::$password === 'admin'; + $shouldRandomizePassword = SeedSetupAdmin::$password === ''; $adminPassword = $shouldRandomizePassword ? Str::random(22) : SeedSetupAdmin::$password; Eloquent::unguarded(function () use ($adminPassword) { diff --git a/modules/backend/database/seeds/SeedSetupAdmin.php b/modules/backend/database/seeds/SeedSetupAdmin.php index c0655bafb0..77967382d6 100644 --- a/modules/backend/database/seeds/SeedSetupAdmin.php +++ b/modules/backend/database/seeds/SeedSetupAdmin.php @@ -9,7 +9,7 @@ class SeedSetupAdmin extends Seeder { public static $email = 'admin@example.com'; public static $login = 'admin'; - public static $password = 'admin'; + public static $password = ''; public static $firstName = 'Admin'; public static $lastName = 'Person'; diff --git a/modules/backend/formwidgets/FileUpload.php b/modules/backend/formwidgets/FileUpload.php index 034c9f69a3..ae401ad6f4 100644 --- a/modules/backend/formwidgets/FileUpload.php +++ b/modules/backend/formwidgets/FileUpload.php @@ -2,6 +2,7 @@ use Db; use Input; +use Event; use Request; use Response; use Validator; @@ -366,8 +367,7 @@ public function onLoadAttachmentConfig() $this->vars['file'] = $file; $this->vars['displayMode'] = $this->getDisplayMode(); $this->vars['cssDimensions'] = $this->getCssDimensions(); - $this->vars['relationManageId'] = post('manage_id'); - $this->vars['relationField'] = post('_relation_field'); + $this->vars['parentElementId'] = $this->getId(); return $this->makePartial('config_form'); } @@ -423,40 +423,47 @@ public function getSaveValue($value) public function onUpload() { try { - if (!Input::hasFile('file_data')) { - throw new ApplicationException('File missing from request'); - } - - $fileModel = $this->getRelationModel(); - $uploadedFile = Input::file('file_data'); - - $validationRules = ['max:'.$fileModel::getMaxFilesize()]; - if ($fileTypes = $this->getAcceptedFileTypes()) { - $validationRules[] = 'extensions:'.$fileTypes; - } - - if ($this->mimeTypes) { - $validationRules[] = 'mimes:'.$this->mimeTypes; - } - - $validation = Validator::make( - ['file_data' => $uploadedFile], - ['file_data' => $validationRules] - ); - - if ($validation->fails()) { - throw new ValidationException($validation); - } + $file = $this->getRelationModel(); + $fileRelation = $this->getRelationObject(); + $file->is_public = $fileRelation->isPublic(); - if (!$uploadedFile->isValid()) { - throw new ApplicationException('File is not valid'); + /** + * @event backend.formwidgets.fileupload.onUpload + * Provides an opportunity to process the file upload using custom logic. + * + * Example usage () + */ + if (!($data = Event::fire('backend.formwidgets.fileupload.onUpload', [$this, $file], true))) { + if (!Input::hasFile('file_data')) { + throw new ApplicationException('File missing from request'); + } + + $validationRules = ['max:'.$file::getMaxFilesize()]; + $data = Input::file('file_data'); + + if (!$data->isValid()) { + throw new ApplicationException('File is not valid'); + } + + if ($fileTypes = $this->getAcceptedFileTypes()) { + $validationRules[] = 'extensions:'.$fileTypes; + } + + if ($this->mimeTypes) { + $validationRules[] = 'mimes:'.$this->mimeTypes; + } + + $validation = Validator::make( + ['file_data' => $data], + ['file_data' => $validationRules] + ); + + if ($validation->fails()) { + throw new ValidationException($validation); + } } - $fileRelation = $this->getRelationObject(); - - $file = $fileModel; - $file->data = $uploadedFile; - $file->is_public = $fileRelation->isPublic(); + $file->data = $data; $file->save(); /** diff --git a/modules/backend/formwidgets/RecordFinder.php b/modules/backend/formwidgets/RecordFinder.php index e4d40ce0f8..3ea6522c68 100644 --- a/modules/backend/formwidgets/RecordFinder.php +++ b/modules/backend/formwidgets/RecordFinder.php @@ -296,6 +296,9 @@ public function onFindRecord() { $this->prepareVars(); + // Attach the parent element ID to the popup + $this->vars['parentElementId'] = $this->getId('popupTrigger'); + /* * Purge the search term stored in session */ diff --git a/modules/backend/formwidgets/codeeditor/assets/js/build-min.js b/modules/backend/formwidgets/codeeditor/assets/js/build-min.js index 1799e5c418..b79f633239 100644 --- a/modules/backend/formwidgets/codeeditor/assets/js/build-min.js +++ b/modules/backend/formwidgets/codeeditor/assets/js/build-min.js @@ -2315,7 +2315,7 @@ this.$el.off('dispose-control',this.proxy(this.dispose)) $(window).off('resize',this.proxy(this.onResize)) $(window).off('oc.updateUi',this.proxy(this.onResize))} CodeEditor.prototype.onBeforeRequest=function(){this.$textarea.val(this.editor.getSession().getValue())} -CodeEditor.prototype.onChange=function(){this.$form.trigger('change') +CodeEditor.prototype.onChange=function(){this.$textarea.trigger('change') this.$textarea.trigger('oc.codeEditorChange')} CodeEditor.prototype.onResize=function(){this.editor.resize()} CodeEditor.prototype.onBlur=function(){this.$el.removeClass('editor-focus')} diff --git a/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js b/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js index 7a4fc585f3..583a25f2da 100644 --- a/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js +++ b/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js @@ -280,7 +280,7 @@ } CodeEditor.prototype.onChange = function() { - this.$form.trigger('change') + this.$textarea.trigger('change') this.$textarea.trigger('oc.codeEditorChange') } diff --git a/modules/backend/formwidgets/fileupload/assets/css/fileupload.css b/modules/backend/formwidgets/fileupload/assets/css/fileupload.css index 65e73f588c..2fc811c4e5 100644 --- a/modules/backend/formwidgets/fileupload/assets/css/fileupload.css +++ b/modules/backend/formwidgets/fileupload/assets/css/fileupload.css @@ -44,7 +44,7 @@ .fileupload-config-form .file-upload-modal-image-header{background-color:#FEFEFE;background-image:-webkit-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-webkit-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:-moz-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-moz-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:-o-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-o-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:-ms-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-ms-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);-webkit-background-size:20px 20px;-moz-background-size:20px 20px;background-size:20px 20px;background-position:0 0,10px 10px} .fileupload-config-form .file-upload-modal-image-header, .fileupload-config-form .file-upload-modal-image-header img{border-top-right-radius:2px;border-top-left-radius:2px} -.fileupload-config-form .file-upload-modal-image-header .close{position:absolute;top:20px;right:20px;background:#BDC3C7;opacity:.7;height:24px;width:22px} +.fileupload-config-form .file-upload-modal-image-header .close{position:absolute;top:20px;right:20px;background:#BDC3C7;opacity:.7;height:24px;width:22px;z-index:1} .fileupload-config-form .file-upload-modal-image-header .close:hover, .fileupload-config-form .file-upload-modal-image-header .close:focus{opacity:.9} .fileupload-config-form .file-upload-modal-image-header + .modal-body{padding-top:20px} diff --git a/modules/backend/formwidgets/fileupload/assets/js/fileupload.js b/modules/backend/formwidgets/fileupload/assets/js/fileupload.js index eb8ad80bba..4b98fe9a9e 100644 --- a/modules/backend/formwidgets/fileupload/assets/js/fileupload.js +++ b/modules/backend/formwidgets/fileupload/assets/js/fileupload.js @@ -135,6 +135,8 @@ this.dropzone.on('sending', this.proxy(this.onUploadSending)) this.dropzone.on('success', this.proxy(this.onUploadSuccess)) this.dropzone.on('error', this.proxy(this.onUploadError)) + + Snowboard.globalEvent("formwidgets.fileupload.initUploader", this); } FileUpload.prototype.onResizeFileInfo = function(file) { @@ -219,6 +221,9 @@ this.$el.closest('[data-field-name]').trigger('change.oc.formwidget') } + /* + * Add the required additional data to the fileupload request + */ FileUpload.prototype.addExtraFormData = function(formData) { if (this.options.extraData) { $.each(this.options.extraData, function (name, value) { @@ -226,10 +231,13 @@ }) } + // Add the data from the containing form element to the upload request to + // ensure that the widget is properly initialized to handle the upload var $form = this.$el.closest('form') if ($form.length > 0) { - $.each($form.serializeArray(), function (index, field) { - formData.append(field.name, field.value) + var requestParentData = $form.getRequestParentData() + $.each(requestParentData, function (key) { + formData.append(key, this) }) } } diff --git a/modules/backend/formwidgets/fileupload/assets/less/fileupload.base.less b/modules/backend/formwidgets/fileupload/assets/less/fileupload.base.less index d8804ca9f3..a380b0ea27 100644 --- a/modules/backend/formwidgets/fileupload/assets/less/fileupload.base.less +++ b/modules/backend/formwidgets/fileupload/assets/less/fileupload.base.less @@ -400,6 +400,7 @@ opacity: .7; height: 24px; width: 22px; + z-index: 1; &:hover, &:focus { opacity: .9; diff --git a/modules/backend/formwidgets/fileupload/partials/_config_form.php b/modules/backend/formwidgets/fileupload/partials/_config_form.php index aad7b4ac87..a652a2485a 100644 --- a/modules/backend/formwidgets/fileupload/partials/_config_form.php +++ b/modules/backend/formwidgets/fileupload/partials/_config_form.php @@ -1,8 +1,6 @@
- + "#{$parentElementId}"]) ?> - -
diff --git a/modules/backend/formwidgets/mediafinder/assets/js/mediafinder.js b/modules/backend/formwidgets/mediafinder/assets/js/mediafinder.js index 60030f955c..e03a97445a 100644 --- a/modules/backend/formwidgets/mediafinder/assets/js/mediafinder.js +++ b/modules/backend/formwidgets/mediafinder/assets/js/mediafinder.js @@ -44,11 +44,11 @@ this.$el.one('dispose-control', this.proxy(this.dispose)) if (this.options.thumbnailWidth > 0) { - this.$el.css('maxWidth', this.options.thumbnailWidth + 'px') + this.$el.find('[data-find-image]').css('maxWidth', this.options.thumbnailWidth + 'px') } else if (this.options.thumbnailHeight > 0) { - this.$el.css('maxHeight', this.options.thumbnailHeight + 'px') + this.$el.find('[data-find-image]').css('maxHeight', this.options.thumbnailHeight + 'px') } // Stop here for preview mode diff --git a/modules/backend/formwidgets/recordfinder/partials/_recordfinder.php b/modules/backend/formwidgets/recordfinder/partials/_recordfinder.php index 16d6598f9a..79ad7f4fe9 100644 --- a/modules/backend/formwidgets/recordfinder/partials/_recordfinder.php +++ b/modules/backend/formwidgets/recordfinder/partials/_recordfinder.php @@ -34,6 +34,7 @@ class="btn btn-default clear-record" diff --git a/modules/backend/formwidgets/richeditor/assets/js/build-plugins-min.js b/modules/backend/formwidgets/richeditor/assets/js/build-plugins-min.js index 59d0d62461..85556851b3 100644 --- a/modules/backend/formwidgets/richeditor/assets/js/build-plugins-min.js +++ b/modules/backend/formwidgets/richeditor/assets/js/build-plugins-min.js @@ -145,7 +145,8 @@ this.$textarea.on('froalaEditor.paste.beforeCleanup',this.proxy(this.beforeClean this.$form.on('oc.beforeRequest',this.proxy(this.onFormBeforeRequest)) this.$textarea.froalaEditor(froalaOptions) this.editor=this.$textarea.data('froala.editor') -if(this.options.readOnly){this.editor.edit.off()}this.$el.on('keydown','.fr-view figure',this.proxy(this.onFigureKeydown))} +if(this.options.readOnly){this.editor.edit.off()}this.$el.on('keydown','.fr-view figure',this.proxy(this.onFigureKeydown)) +Snowboard.globalEvent("formwidgets.richeditor.init",this)} RichEditor.prototype.dispose=function(){this.unregisterHandlers() this.$textarea.froalaEditor('destroy') this.$el.removeData('oc.richEditor') @@ -198,7 +199,7 @@ RichEditor.prototype.onBlur=function(){this.$el.removeClass('editor-focus')} RichEditor.prototype.onFigureKeydown=function(ev){this.$textarea.trigger('figureKeydown.oc.richeditor',[ev,this])} RichEditor.prototype.onKeydown=function(ev,editor,keyEv){this.$textarea.trigger('keydown.oc.richeditor',[keyEv,this]) if(ev.isDefaultPrevented()){return false}} -RichEditor.prototype.onChange=function(ev){this.$form.trigger('change')} +RichEditor.prototype.onChange=function(ev){this.$textarea.trigger('change')} RichEditor.prototype.onFormBeforeRequest=function(ev){if(!this.editor){return}if(this.isCodeViewActive()){this.editor.html.set(this.editor.codeView.get())}this.$textarea.val(this.editor.html.get())} var old=$.fn.richEditor $.fn.richEditor=function(option){var args=Array.prototype.slice.call(arguments,1),result diff --git a/modules/backend/formwidgets/richeditor/assets/js/richeditor.js b/modules/backend/formwidgets/richeditor/assets/js/richeditor.js index 70dcd27db1..e1ef2d77c7 100755 --- a/modules/backend/formwidgets/richeditor/assets/js/richeditor.js +++ b/modules/backend/formwidgets/richeditor/assets/js/richeditor.js @@ -238,6 +238,8 @@ } this.$el.on('keydown', '.fr-view figure', this.proxy(this.onFigureKeydown)) + + Snowboard.globalEvent("formwidgets.richeditor.init",this) } RichEditor.prototype.dispose = function() { @@ -403,7 +405,7 @@ } RichEditor.prototype.onChange = function(ev) { - this.$form.trigger('change') + this.$textarea.trigger('change') } /* diff --git a/modules/backend/lang/be/lang.php b/modules/backend/lang/be/lang.php index ddbfefc87e..181f479f45 100644 --- a/modules/backend/lang/be/lang.php +++ b/modules/backend/lang/be/lang.php @@ -332,7 +332,7 @@ 'theme' => "Каляровая схема", 'markup_styles' => "Стылі макету", 'custom_styles' => "Прыстасаваныя табліцы стыляў", - 'custom styles_comment' => "Прыстасаваныя стылі якія патрэбна дадаць у рэдактар", + 'custom_styles_comment' => "Прыстасаваныя стылі якія патрэбна дадаць у рэдактар", 'markup_classes' => "Класы макету", 'paragraph' => "Параграф", 'link' => "Спасылка", diff --git a/modules/backend/lang/ca/lang.php b/modules/backend/lang/ca/lang.php index 108adbad01..04a26179a4 100644 --- a/modules/backend/lang/ca/lang.php +++ b/modules/backend/lang/ca/lang.php @@ -365,7 +365,7 @@ 'theme' => 'Esquema de color', 'markup_styles' => 'Estils de marcat', 'custom_styles' => "Full d'estils personalitzat", - 'custom styles_comment' => "Estils personalitzats per incloure a l'editor HTML.", + 'custom_styles_comment' => "Estils personalitzats per incloure a l'editor HTML.", 'markup_classes' => 'Classes de marcat', 'paragraph' => 'Paràgraf', 'link' => 'Enllaç', diff --git a/modules/backend/lang/cs/lang.php b/modules/backend/lang/cs/lang.php index 782b0b1f27..e0852841b4 100644 --- a/modules/backend/lang/cs/lang.php +++ b/modules/backend/lang/cs/lang.php @@ -356,7 +356,7 @@ 'theme' => 'Barevné schéma', 'markup_styles' => 'Styly', 'custom_styles' => 'Vlastní styly', - 'custom styles_comment' => 'Vlastní styly, které chcete zahrnout do editoru HTML.', + 'custom_styles_comment' => 'Vlastní styly, které chcete zahrnout do editoru HTML.', 'markup_classes' => 'Třídy stylů', 'paragraph' => 'Odstavec', 'link' => 'Odkaz', diff --git a/modules/backend/lang/da/lang.php b/modules/backend/lang/da/lang.php index af6ae4a5c0..f7d181d925 100644 --- a/modules/backend/lang/da/lang.php +++ b/modules/backend/lang/da/lang.php @@ -323,7 +323,7 @@ 'theme' => 'Farveskema', 'markup_styles' => 'Markup Styles', 'custom_styles' => 'Custom stylesheet', - 'custom styles_comment' => 'Custom styles som skal inkluderes i HTML editoren.', + 'custom_styles_comment' => 'Custom styles som skal inkluderes i HTML editoren.', 'markup_classes' => 'Markup Classes', 'paragraph' => 'Afsnit', 'link' => 'Link', diff --git a/modules/backend/lang/de/lang.php b/modules/backend/lang/de/lang.php index 9c8148c1a5..8f371dae9f 100644 --- a/modules/backend/lang/de/lang.php +++ b/modules/backend/lang/de/lang.php @@ -3,48 +3,56 @@ return [ 'auth' => [ 'title' => 'Admin-Bereich', - 'invalid_login' => 'Die Angaben stimmen nicht mit unseren Aufzeichnungen überein. Überprüfen Sie diese und versuchen Sie es noch einmal.', + 'invalid_login' => 'Die Angaben stimmen nicht mit unseren Einträgen überein. Überprüfen Sie diese und versuchen Sie es noch einmal.', ], 'field' => [ 'invalid_type' => 'Ungültiger Feldtyp :type.', - 'options_method_invalid_model' => 'Das Attribut ":field" löst sich nicht zu einen gültigen Model auf. Probiere die options Methode der Model-Klasse :model explicit zu definieren.', - 'options_method_not_exists' => 'Die Modell-Klasse :model muss eine Methode :method() mit Rückgabe der Werte von ":field" besitzen.', - 'options_static_method_invalid_value' => "Die statische Methode ':method()' in der Klasse :class hat kein valides Optionsarray zurückgegeben.", - 'colors_method_not_exists' => "Die Modellklasse :model muss eine Methode :method() definieren, welche html color (HEX) codes für das ':field' Formularfeld zurückgibt.", + 'options_method_invalid_model' => 'Das Attribut ":field" löst sich nicht zu einen gültigen Model auf. Probieren Sie die options-Methode der Model-Klasse :model explicit zu definieren.', + 'options_method_not_exists' => 'Die Model-Klasse :model muss eine Methode :method() mit Rückgabe der Werte von ":field" besitzen.', + 'options_static_method_invalid_value' => 'Die statische Methode ":method()" in der Klasse :class hat kein valides Options-Array zurückgegeben.', + 'colors_method_not_exists' => 'Die Model-Klasse :model muss eine Methode :method() definieren, welche HTML-Farbcodes (HEX) für das ":field"-Formularfeld zurückgibt.', ], 'widget' => [ - 'not_registered' => "Ein Widget namens ':name' wurde nicht registriert", - 'not_bound' => "Ein Widget mit dem Klassennamen ':name' wurde nicht mit dem Controller verbunden", + 'not_registered' => 'Ein Widget namens ":name" wurde nicht registriert', + 'not_bound' => 'Ein Widget mit dem Klassennamen ":name" wurde nicht mit dem Controller verbunden', ], 'page' => [ - 'untitled' => "Unbenannt", + 'untitled' => 'Unbenannt', '404' => [ 'label' => 'Seite nicht gefunden', - 'help' => "Die von Ihnen angeforderte Seite konnte nicht gefunden werden.", - 'back_link' => 'Zurück zur vorigen Seite', + 'help' => 'Die von Ihnen angeforderte Seite konnte nicht gefunden werden.', + 'back_link' => 'Zurück zur vorherigen Seite', ], 'access_denied' => [ - 'label' => "Zugriff verweigert", - 'help' => "Sie haben nicht die erforderlichen Berechtigungen, um diese Seite zu sehen.", - 'cms_link' => "Zum CMS-Backend", + 'label' => 'Zugriff verweigert', + 'help' => 'Sie haben nicht die erforderlichen Berechtigungen, um diese Seite zu sehen.', + 'cms_link' => 'Zum CMS-Backend', ], 'no_database' => [ 'label' => 'Datenbank fehlt', - 'help' => "Eine Datenbank wird benötigt um Zugriff auf das Backend zu haben. Überprüfe die Datenbankkonfiguration und migriere die Datenbank bevor du es noch einmal probierst.", - 'cms_link' => 'Zurück zur Homepage' + 'help' => 'Eine Datenbank wird benötigt um Zugriff auf das Backend zu haben. Überprüfen Sie die Datenbankkonfiguration und migrieren Sie die Datenbank bevor Sie es noch einmal probieren.', + 'cms_link' => 'Zurück zur Homepage', ], ], 'partial' => [ - 'not_found_name' => "Das Partial ':name' wurde nicht gefunden.", - 'invalid_name' => 'Ungültiger Partial: :name.', + 'not_found_name' => 'Das Partial ":name" wurde nicht gefunden.', + 'invalid_name' => 'Ungültiges Partial: :name.', ], 'ajax_handler' => [ - 'invalid_name' => 'Ungültiger AJAX handler: :name.', - 'not_found' => "AJAX handler ':name' wurde nicht gefunden.", + 'invalid_name' => 'Ungültiger AJAX-Handler: :name.', + 'not_found' => 'AJAX-Handler ":name" wurde nicht gefunden.', ], 'account' => [ 'impersonate_confirm' => 'Sind Sie sicher, dass Sie sich als dieser Benutzer anmelden wollen? Sie können zu Ihrem ursprünglichen Zustand zurückkehren, indem Sie sich abmelden.', 'impersonate_success' => 'Sie sind jetzt als dieser Benutzer angemeldet', + 'impersonate_success' => 'Sie imitieren jetzt diesen Benutzer', + 'impersonate_working' => 'Imitiere...', + 'impersonating' => 'Sie sind jetzt temporär eingeloogt als :impersonatee. Log-Dateien indentifizieren Sie jedoch als :impersonator', + 'stop_impersonating' => 'Imitieren beenden', + 'unsuspend' => 'Entsperren', + 'unsuspend_confirm' => 'Sind Sie sicher, dass Sie diesen Benutzer entsperren wollen?', + 'unsuspend_success' => 'Benutzer wurde entsperrt.', + 'unsuspend_working' => 'Entsperre...', 'signed_in_as' => 'Angemeldet als :full_name', 'sign_out' => 'Abmelden', 'login' => 'Anmelden', @@ -53,16 +61,16 @@ 'login_placeholder' => 'Benutzername', 'password_placeholder' => 'Passwort', 'remember_me' => 'Angemeldet bleiben', - 'forgot_password' => "Passwort vergessen?", - 'enter_email' => "Bitte E-Mail-Adresse eingeben", - 'enter_login' => "Bitte Benutzernamen eingeben", - 'email_placeholder' => "E-Mail", - 'enter_new_password' => "Bitte ein neues Passwort eingeben", - 'password_reset' => "Passwort zurücksetzen", - 'restore_success' => "Eine E-Mail mit weiteren Anweisungen zum Zurücksetzen Ihres Passworts wurde an Sie versandt", - 'reset_success' => "Ihr Passwort wurde erfolgreich zurückgesetzt. Sie können sich jetzt anmelden.", - 'reset_error' => "Konnte Passwort nicht zurücksetzen. Bitte erneut versuchen!", - 'reset_fail' => "Passwort-Zurücksetzung nicht möglich!", + 'forgot_password' => 'Passwort vergessen?', + 'enter_email' => 'Bitte E-Mail-Adresse eingeben', + 'enter_login' => 'Bitte Benutzernamen eingeben', + 'email_placeholder' => 'E-Mail', + 'enter_new_password' => 'Bitte ein neues Passwort eingeben', + 'password_reset' => 'Passwort zurücksetzen', + 'restore_success' => 'Eine E-Mail mit weiteren Anweisungen zum Zurücksetzen Ihres Passworts wurde an Sie versandt.', + 'reset_success' => 'Ihr Passwort wurde erfolgreich zurückgesetzt. Sie können sich jetzt anmelden.', + 'reset_error' => 'Konnte Passwort nicht zurücksetzen. Bitte erneut versuchen!', + 'reset_fail' => 'Passwort-Zurücksetzung nicht möglich!', 'apply' => 'Anwenden', 'cancel' => 'Abbrechen', 'delete' => 'Löschen', @@ -72,31 +80,31 @@ 'menu_label' => 'Dashboard', 'widget_label' => 'Widget', 'widget_width' => 'Breite', - 'full_width' => 'ganze Breite', + 'full_width' => 'Volle Breite', 'manage_widgets' => 'Widgets verwalten', 'add_widget' => 'Neues Widget', - 'widget_inspector_title' => 'Widget Konfiguration', + 'widget_inspector_title' => 'Widget-Konfiguration', 'widget_inspector_description' => 'Dieses Widget konfigurieren', 'widget_columns_label' => 'Breite :columns', - 'widget_columns_description' => 'Die Breite de Widgets, eine Zahl zwischen 1 und 10.', - 'widget_columns_error' => 'Bitte geben sie als Breite des Widgets eine Zahl zwischen 1 und 10 ein.', + 'widget_columns_description' => 'Die Breite des Widgets, eine Zahl zwischen 1 und 10.', + 'widget_columns_error' => 'Bitte geben Sie als Breite des Widgets eine Zahl zwischen 1 und 10 ein.', 'columns' => '{1} Spalte|[2,Inf] Spalten', - 'widget_new_row_label' => 'Neue Reihe erzwingen', - 'widget_new_row_description' => 'Setzt das Widget in eine neue Reihe', + 'widget_new_row_label' => 'Neue Zeile erzwingen', + 'widget_new_row_description' => 'Setzt das Widget in eine neue Zeile', 'widget_title_label' => 'Titel des Widgets', - 'widget_title_error' => 'Ein Titel des Widgets wird benötigt.', + 'widget_title_error' => 'Das Widgets benötigt einen Titel.', 'reset_layout' => 'Layout zurücksetzen', 'reset_layout_confirm' => 'Layout auf Ursprungszustand zurücksetzen', 'reset_layout_success' => 'Layout wurde zurückgesetzt', 'make_default' => 'Setze Standard', - 'make_default_confirm' => 'Das aktuelle Layout and Standard setzen', + 'make_default_confirm' => 'Das aktuelle Layout auf Standard setzen', 'make_default_success' => 'Das aktuelle Layout ist nun das Standardlayout', - 'collapse_all' => 'Alles zusammenklappen', + 'collapse_all' => 'Alles einklappen', 'expand_all' => 'Alles ausklappen', 'status' => [ - 'widget_title_default' => 'System Status', + 'widget_title_default' => 'System-Status', 'update_available' => '{0} Updates verfügbar!|{1} Update verfügbar!|[2,Inf] Updates verfügbar!', - 'updates_pending' => 'Software ', + 'updates_pending' => 'Ausstehende Software Updates', 'updates_nil' => 'Software ist auf dem neuesten Stand', 'updates_link' => 'Update', 'warnings_pending' => 'Es sind Probleme aufgetreten', @@ -113,9 +121,9 @@ 'welcome_to_name' => 'Willkommen zu :app, :name.', 'first_sign_in' => 'Das ist das erste mal, dass Sie sich eingeloggt haben.', 'last_sign_in' => 'Ihr letzter Login war', - 'view_access_logs' => 'Zugriffsprotokoll betrachten', + 'view_access_logs' => 'Zugriffsprotokoll einsehen', 'nice_message' => 'Wir wünschen einen schönen Tag!', - ] + ], ], 'user' => [ 'name' => 'Administrator', @@ -126,7 +134,7 @@ 'login' => 'Benutzername', 'first_name' => 'Vorname', 'last_name' => 'Nachname', - 'full_name' => 'Kompletter Name', + 'full_name' => 'Vollständiger Name', 'email' => 'E-Mail', 'role_field' => 'Rolle', 'role_comment' => 'Rollen definieren Benutzerberechtigungen, die auf Benutzerebene auf der Registerkarte Berechtigungen überschrieben werden können.', @@ -138,38 +146,40 @@ 'permissions' => 'Rechte', 'account' => 'Account', 'superuser' => 'Super-User', - 'superuser_comment' => 'Bestätigen Sie hier, um dem Nutzer Vollzugriff zu geben', + 'superuser_comment' => 'Bestätigen Sie hier, um dem Nutzer Vollzugriff zu gestatten', 'send_invite' => 'Einladung per E-Mail versenden', 'send_invite_comment' => 'Hier bestätigen, dass eine Einladung per E-Mail erfolgt', 'delete_confirm' => 'Möchten Sie diesen Administrator-Account wirklich löschen?', - 'return' => 'Zurück zur Administratoren Übersicht', + 'return' => 'Zurück zur Administratoren-Übersicht', 'allow' => 'Zulassen', 'inherit' => 'Vererben', 'deny' => 'Verbieten', 'activated' => 'Aktiviert', - 'last_login' => 'Letzer login', + 'last_login' => 'Letzer Login', 'created_at' => 'Erstellt am', 'updated_at' => 'Aktualisiert am', + 'deleted_at' => 'Gelöscht am', + 'show_deleted' => 'Zeige gelöschte', 'group' => [ 'name' => 'Gruppe', - 'name_comment' => 'Der Name, der angezeigt wird wenn name is displayed in the group list on the Create/Edit Administrator form.', + 'name_comment' => 'Der Anzeigename, der in der Gruppen-Liste im Administrator-Formular angezeigt wird.', 'name_field' => 'Name', 'description_field' => 'Beschreibung', 'is_new_user_default_field_label' => 'Standard Gruppe', - 'is_new_user_default_field_comment' => 'Fügt neue Administratoren zu dieser Gruppe standardmäßig hinzu.', + 'is_new_user_default_field_comment' => 'Fügt neue Administratoren zu dieser Gruppe automatisch hinzu.', 'code_field' => 'Code', 'code_comment' => 'Eindeutigen Code hinzufügen, wenn dies über die API bearbeitet werden soll.', 'menu_label' => 'Gruppen', 'list_title' => 'Gruppen verwalten', - 'new' => 'Neue Administratoren Gruppe', - 'delete_confirm' => 'Möchten Sie diesen Administratoren-Gruppe wirklich löschen?', + 'new' => 'Neue Administratoren-Gruppe', + 'delete_confirm' => 'Möchten Sie diese Administratoren-Gruppe wirklich löschen?', 'return' => 'Zurück zur Gruppen-Übersicht', 'users_count' => 'Benutzer', ], 'role' => [ 'name' => 'Rolle', 'name_field' => 'Name', - 'name_comment' => 'Der Name wird in der Rollenliste auf dem Administratorformular angezeigt.', + 'name_comment' => 'Der Name wird in der Rollen-Liste auf dem Administrator-Formular angezeigt.', 'description_field' => 'Beschreibung', 'code_field' => 'Code', 'code_comment' => 'Geben Sie einen eindeutigen Code an, wenn Sie mit der API auf das Rollenobjekt zugreifen möchten.', @@ -177,27 +187,27 @@ 'list_title' => 'Rollen verwalten', 'new' => 'Neue Rolle', 'delete_confirm' => 'Diese Administratorrolle löschen?', - 'return' => 'Zurück zur Rollenliste', + 'return' => 'Zurück zur Rollen-Liste', 'users_count' => 'Benutzer', ], 'preferences' => [ - 'not_authenticated' => 'Zum Speichern oder Anzeigen dieser Einstellungen liegt kein Nutzerkonto vor' + 'not_authenticated' => 'Zum Speichern oder Anzeigen dieser Einstellungen liegt kein Benutzerkonto vor.', ], - 'trashed_hint_title' => 'Dieses Konto wurde gelöscht.', - 'trashed_hint_desc' => 'Dieses Konto wurde gelöscht und kann nicht mehr angemeldet werden. Um es wiederherzustellen, klicken Sie auf das Symbol "Benutzer wiederherstellen" unten rechts', + 'trashed_hint_title' => 'Dieser Benutzer wurde gelöscht.', + 'trashed_hint_desc' => 'Dieser Benutzer wurde gelöscht und kann sich nicht mehr anmelden. Um ihn wiederherzustellen, klicken Sie auf das Symbol "Benutzer wiederherstellen" unten rechts', ], 'list' => [ 'default_title' => 'Auflisten', 'search_prompt' => 'Suchen...', - 'no_records' => 'Keine Ergebnisse für diese Ansicht gefunden', - 'missing_model' => 'In :class benutztes Lisstenverhalten hat kein Model definiert.', + 'no_records' => 'Es wurden keine Ergebnisse für diese Ansicht gefunden.', + 'missing_model' => 'In der Klasse :class wurde für das Listenverhalten (Behaviour) kein Model definiert.', 'missing_column' => 'Keine Spaltendefinition für :columns.', - 'missing_columns' => 'In :class benutzte Liste behinhaltet keine Spalten', - 'missing_definition' => "Der Liste fehlt eine Spalte für ':field'.", - 'missing_parent_definition' => "Listenverhalten beinhaltet keine Definition von ':definition'.", + 'missing_columns' => 'Die Klasse :class hat im Listeverhalten (Behaviour) keine Spalten definiert.', + 'missing_definition' => 'Der Liste fehlt eine Spalte für ":field".', + 'missing_parent_definition' => 'Listenverhalten (Behaviour) beinhaltet keine Definition von ":definition".', 'behavior_not_ready' => 'Listenverhalten kann nicht initialisiert werden, überprüfen Sie den Aufruf von makeLists() in Ihrem Controller.', - 'invalid_column_datetime' => "Spaltenwert ':column' ist kein gültiges DateTime Objekt, haben Sie eine \$dates Referenz in dem Model vergessen?", - 'pagination' => 'Angezeigte Aufzeichnungen: :from-:to von :total', + 'invalid_column_datetime' => ' Der Spaltenwert ":column" ist kein gültiges DateTime-Objekt, haben Sie eine \$dates-Referenz in dem Model vergessen?', + 'pagination' => 'Angezeigte Einträge: :from-:to von :total', 'first_page' => 'Erste Seite', 'last_page' => 'Letzte Seite', 'prev_page' => 'Vorherige Seite', @@ -205,17 +215,17 @@ 'refresh' => 'Erneuern', 'updating' => 'Aktualisiere...', 'loading' => 'Laden...', - 'setup_title' => 'Listen Setup', - 'setup_help' => 'Benutzen Sie Checkboxen, um Spalten auszuwählen, welche Sie in den Listen sehen möchten. Sie können die Position der Spalten ändern, indem Sie diese hinauf oder hinunter ziehen.', + 'setup_title' => 'Listen-Einstellungen', + 'setup_help' => 'Benutzen Sie Checkboxen, um Spalten auszuwählen, welche Sie in den Listen sehen möchten. Sie können die Position der Spalten ändern, indem Sie diese hoch oder runter ziehen.', 'records_per_page' => 'Aufzeichnungen pro Seite', - 'records_per_page_help' => 'Wählen Sie, wieviele Aufzeichnungen pro Seite dargestellt werden sollen. Bitte beachten Sie, dass eine hohe Anzahl pro Seite die Performance negativ beeinflussen kann.', + 'records_per_page_help' => 'Wählen Sie, wie viele Einträge pro Seite dargestellt werden sollen. Bitte beachten Sie, dass eine hohe Anzahl pro Seite die Performance negativ beeinflussen kann.', 'check' => 'Gesetzt', 'delete_selected' => 'Markierte löschen', 'delete_selected_empty' => 'Keine Einträge zum Löschen markiert.', 'delete_selected_confirm' => 'Markierte Einträge löschen?', 'delete_selected_success' => 'Markierte Einträge erfolgreich gelöscht.', 'column_switch_true' => 'Ja', - 'column_switch_false' => 'Nein' + 'column_switch_false' => 'Nein', ], 'fileupload' => [ 'attachment' => 'Anhang', @@ -235,17 +245,18 @@ 'max_items_failed' => ':name lässt nur bis zu :max Elemente zu, :items wurden bereitgestellt', ], 'form' => [ - 'create_title' => "Neuer :name", - 'update_title' => "Bearbeite :name", - 'preview_title' => "Vorschau für :name", + 'create_title' => 'Neuer :name', + 'update_title' => 'Bearbeite :name', + 'preview_title' => 'Vorschau für :name', 'create_success' => ':name wurde erfolgreich erzeugt', 'update_success' => ':name wurde erfolgreich aktualisiert', 'delete_success' => ':name wurde erfolgreich gelöscht', + 'restore_success' => ':name wurde erfolgreich wiederhergestellt', 'reset_success' => 'Zurücksetzung abgeschlossen', - 'missing_id' => "Formulardatensatz-ID (Form record ID) fehlt.", - 'missing_model' => 'In :class genutztes Formularverhalten (behaviour) hat kein definiertes Model', - 'missing_definition' => "Formverhalten fehlt ein Feld für ':field'.", - 'not_found' => 'Formulareintrag mit der ID :id kann nicht gefunden werden.', + 'missing_id' => 'Datensatz-ID (Form record ID) fehlt.', + 'missing_model' => 'Das in der Klasse :class genutztes Formularverhalten (Behaviour) hat kein definiertes Model', + 'missing_definition' => 'Formverhalten (Behaviour) fehlt ein Feld für ":field".', + 'not_found' => 'Der Formulareintrag mit der ID :id kann nicht gefunden werden.', 'action_confirm' => 'Sind Sie sich sicher?', 'create' => 'Erstellen', 'create_and_close' => 'Erstellen und schließen', @@ -259,7 +270,10 @@ 'deleting' => 'Löschen...', 'confirm_delete' => 'Wollen Sie diesen Eintrag wirklich löschen?', 'confirm_delete_multiple' => 'Wollen Sie diese Einträge wirklich löschen?', - 'deleting_name' => 'Deleting :name...', + 'deleting_name' => 'Lösche :name...', + 'restore' => 'Wiederherstellen', + 'restoring' => 'Wiederherstellen...', + 'confirm_restore' => 'Sind Sie sicher, dass Sie den Eintrag wiederherstellen möchten?', 'reset_default' => 'Zurücksetzen', 'resetting' => 'Setze zurück...', 'resetting_name' => 'Setze :name zurück...', @@ -281,127 +295,136 @@ 'preview_no_media_message' => 'Es wurde keine Media-Datei ausgewählt.', 'preview_no_record_message' => 'Es ist kein Eintrag ausgewählt.', 'select' => 'Auswählen', - 'select_all' => 'Wählen Sie Alle', - 'select_none' => 'nichts ausgewählt', + 'select_all' => 'Alle auswählen', + 'select_none' => 'Nichts ausgewählt', 'select_placeholder' => 'Bitte auswählen', - 'insert_row' => 'Reihe einfügen', - 'insert_row_below' => 'Neue Reihe darunter einfügen', - 'delete_row' => 'Reihe löschen', + 'insert_row' => 'Zeile einfügen', + 'insert_row_below' => 'Neue Zeile darunter einfügen', + 'delete_row' => 'Zeile löschen', 'concurrency_file_changed_title' => 'Datei wurde geändert', - 'concurrency_file_changed_description' => 'Die Datei, welche Sie bearbeiten, wurde auf von einem anderen Benutzer geändert. Sie können die Datei entweder erneut laden, wodurch Ihre Änderungen verloren gehen oder Sie überschreiben die Datei auf dem Server', - 'return_to_list' => 'Zurück zur Liste' + 'concurrency_file_changed_description' => 'Die Datei, welche Sie bearbeiten, wurde von einem anderen Benutzer geändert. Sie können die Datei entweder erneut laden, wodurch Ihre Änderungen verloren gehen oder Sie überschreiben die Datei auf dem Server', + 'return_to_list' => 'Zurück zur Liste', ], 'recordfinder' => [ 'find_record' => 'Finde Eintrag', + 'invalid_model_class' => 'Die angegebene Model-Klasse ":modelClass" für den Eintragsfinder ist ungültig.', 'cancel' => 'Abbrechen', ], 'pagelist' => [ 'page_link' => 'Seitenlink', - 'select_page' => 'Wähle eine Seite...' + 'select_page' => 'Wähle eine Seite...', ], 'relation' => [ - 'missing_config' => "Verhalten (behaviour) der Verbindung hat keine Konfiguration für ':config'.", - 'missing_definition' => "Verhalten (behaviour) der Verbindung umfasst keine Definition für ':field'.", - 'missing_model' => "Verhalten (behaviour) der Verbindung, die in :class benutzt wird, hat kein definiertes Model", - 'invalid_action_single' => "Dieser Vorgang kann nicht auf eine Einwege-Verbindung (singular) angewendet werden.", - 'invalid_action_multi' => "Dieser Vorgang kann nicht auf eine Mehrwege-Verbindung (multiple) angewendet werden.", - 'help' => "Zum Hinzufügen auf ein Item klicken", - 'related_data' => "Verwandte :name Daten", - 'add' => "Hinzufügen", + 'missing_config' => 'Das Verhalten (Behaviour) der Beziehung hat keine Konfiguration für ":config".', + 'missing_definition' => 'Das Verhalten (Behaviour) der Beziehung umfasst keine Definition für ":field".', + 'missing_model' => 'Das Verhalten (Behaviour) der Beziehung, die in :class benutzt wird, hat kein definiertes Model.', + 'invalid_action_single' => 'Dieser Vorgang kann nicht auf eine Einwege-Verbindung (singular) angewendet werden.', + 'invalid_action_multi' => 'Dieser Vorgang kann nicht auf eine Mehrwege-Verbindung (multiple) angewendet werden.', + 'relationwidget_unsupported_type' => 'Der ":type"-Beziehungstyp wird nicht vom Relation-Widget unterstützt.', + 'help' => 'Zum Hinzufügen auf einen Eintrag klicken', + 'related_data' => 'Verwandte :name Daten', + 'add' => 'Hinzufügen', 'add_selected' => 'Auswahl hinzufügen', 'add_a_new' => ':name hinzufügen', 'link_selected' => 'Auswahl verlinken', - 'link_a_new' => ':name verlinken', + 'link_a_new' => ':name verlinken', 'cancel' => 'Abbrechen', 'close' => 'Schließen', - 'add_name' => ":name hinzufügen", - 'create' => "Erstellen", - 'create_name' => "Erstelle :name", - 'update' => "Speichern", - 'update_name' => ":name bearbeiten", + 'add_name' => ':name hinzufügen', + 'create' => 'Erstellen', + 'create_name' => 'Erstelle :name', + 'update' => 'Speichern', + 'update_name' => ':name bearbeiten', 'preview' => 'Vorschau', 'preview_name' => 'Vorschau :name', - 'remove' => "Entfernen", - 'remove_name' => ":name entfernen", - 'delete' => "Löschen", - 'delete_name' => ":name löschen", - 'delete_confirm' => "Sind Sie sicher?", + 'remove' => 'Entfernen', + 'remove_name' => ':name entfernen', + 'delete' => 'Löschen', + 'delete_name' => ':name löschen', + 'delete_confirm' => 'Sind Sie sicher?', 'link' => 'Link', 'link_name' => 'Link :name', 'unlink' => 'Link entfernen', 'unlink_name' => 'Link von :name entfernen', - 'unlink_confirm' => 'Sind Sie sicher?' + 'unlink_confirm' => 'Sind Sie sicher?', ], 'reorder' => [ 'default_title' => 'Einträge sortieren', - 'no_records' => 'Es gibt keine Einträge zum sortieren.' + 'no_records' => 'Es gibt keine Einträge zum sortieren.', ], 'model' => [ - 'name' => "Model", - 'not_found' => "Model ':class' mit ID :id konnte nicht gefunden werden", - 'missing_id' => "Für diesen Model-Datensatz ist keine ID angegeben", - 'missing_relation' => "Model ':class' hat keine definierte Verbindung ':relation'.", - 'missing_method' => "Model ':class' besitzt keine Methode ':method'.", - 'invalid_class' => "In :class benutztes Model :model ist ungültig, da es von der Klasse \Model abgeleitet sein muss (inherit).", - 'mass_assignment_failed' => "Mass assignment failed for Model attribute ':attribute'.", + 'name' => 'Model', + 'not_found' => 'Model ":class" mit ID :id konnte nicht gefunden werden', + 'missing_id' => 'Für diesen Model-Datensatz ist keine ID angegeben', + 'missing_relation' => 'Das Model ":class" hat keine definierte Beziehung ":relation".', + 'missing_method' => 'Das Model ":class" besitzt keine Methode ":method".', + 'invalid_class' => 'In der Klasse :class das benutztes Model :model ist ungültig, da es von der Klasse \Model abgeleitet sein muss (inherit).', + 'mass_assignment_failed' => 'Die Mehrfachzuweisung für das Model-Attribut ":attribute" ist fehlgeschlagen.', ], 'warnings' => [ - 'tips' => 'System Konfigurations Tips', + 'tips' => 'System-Konfigurationstipps', 'tips_description' => 'Es gibt Probleme, welche Sie beachten müssen, um das System korrekt zu konfigurieren.', - 'permissions' => 'Verzeichnis :name oder ein Unterverzeichnis kann nicht von PHP beschrieben werden. Bitte setzen Sie die korrekten Rechte für den Webserver in diesem Verzeichnis.', - 'extension' => 'Die PHP Erweiterung :name ist nicht installiert. Bitte installieren Sie diese Library und aktivieren Sie die Erweiterung.', - 'plugin_missing' => 'Das Plugin :name hat eine Abhängigkeit die nicht installiert ist. Bitte installieren Sie alle benötigten Plugins.', + 'permissions' => 'Das Verzeichnis :name oder ein Unterverzeichnis kann nicht von PHP beschrieben werden. Bitte setzen Sie die korrekten Rechte für den Webserver in diesem Verzeichnis.', + 'extension' => 'Die PHP-Erweiterung :name ist nicht installiert. Bitte installieren und aktivieren Sie diese Erweiterung.', + 'plugin_missing' => 'Das Plugin :name hat eine Abhängigkeit, die nicht installiert ist. Bitte installieren Sie alle benötigten Plugins.', 'debug' => 'Der Debug-Modus ist aktiviert. Dies wird für Produktionsinstallationen nicht empfohlen.', 'decompileBackendAssets' => 'Assets im Backend sind derzeit dekompiliert. Dies wird für Produktionsinstallationen nicht empfohlen.', + 'default_backend_user' => 'Ein Benutzer mit Standard Login-Daten (admin / admin@domain.tld) wurde gefunden. Ändern Sie den Benutzername und / oder die E-Mail-Adresse, um dabei zu helfen das System zu schützen.', ], 'editor' => [ - 'menu_label' => 'Editor Einstellungen', - 'menu_description' => 'Verwalten der Code-Editor Einstellungen.', - 'font_size' => 'Schriftgrösse', - 'tab_size' => 'Tabgrösse', - 'use_hard_tabs' => 'Gedankenstrich bei Tabs', + 'menu_label' => 'Editor-Einstellungen', + 'menu_description' => 'Verwalten der Einstellungen für den Code-Editor.', + 'preview' => 'Vorschau', + 'font_size' => 'Schriftgröße', + 'tab_size' => 'Tabgröße', + 'use_hard_tabs' => 'Einrückungen mit Tabs', 'code_folding' => 'Code-Folding', 'code_folding_begin' => 'Markierungsbeginn', 'code_folding_begin_end' => 'Markierungsbeginn und Ende', 'autocompletion' => 'Autovervollständigung', - 'word_wrap' => 'Word Wrap', + 'word_wrap' => 'Wortumbruch', 'highlight_active_line' => 'Aktive Zeile hervorheben', 'auto_closing' => 'Automatisch Tags schließen', 'show_invisibles' => 'Unsichtbare Zeichen anzeigen', 'show_gutter' => 'Gutter anzeigen', - 'live_autocompletion'=> 'Live Autovervollständigung', - 'enable_snippets'=> 'Aktiviere Code-snippets (Tab)', - 'display_indent_guides'=> 'Zeige Einrückungshilfen', - 'show_print_margin'=> 'Zeige Druckabstand', + 'basic_autocompletion' => 'Basic-Autovervollständigung (Strg + Leertaste)', + 'live_autocompletion' => 'Live-Autovervollständigung', + 'enable_snippets' => 'Aktiviere Code-snippets (Tab)', + 'display_indent_guides' => 'Zeige Einrückungshilfen', + 'show_print_margin' => 'Zeige Druckabstand', 'mode_off' => 'Aus', 'mode_fluid' => 'Fluid', '40_characters' => '40 Zeichen', '80_characters' => '80 Zeichen', 'theme' => 'Farbschema', 'markup_styles' => 'Markup Styles', - 'custom_styles' => 'Custom stylesheet', - 'custom styles_comment' => 'Custom styles im HTML editor einbinden.', - 'markup_classes' => 'Markup Classes', - 'paragraph' => 'Paragraph', + 'custom_styles' => 'Benutzerdefiniertes Stylesheet', + 'custom_styles_comment' => 'Benutzerdefinierte Styles im HTML-Editor einbinden.', + 'markup_classes' => 'Markup-Klassen', + 'paragraph' => 'Absatz', 'link' => 'Link', 'table' => 'Tabelle', 'table_cell' => 'Tabellenzelle', 'image' => 'Bild', 'label' => 'Beschriftung', - 'class_name' => 'Class name', - 'markup_tags' => 'Markup Tags', + 'class_name' => 'Klassen-Name', + 'markup_tags' => 'Markup-Tags', + 'markup_tag' => 'Markup-Tag', 'allowed_empty_tags' => 'Erlaube leere Tags', - 'allowed_empty_tags_comment' => 'Die Liste von Tags welche nicht entfernt werden wenn sie keinen Inhalt haben (leer sind).', - 'allowed_tags' => 'Erlaubte tags', + 'allowed_empty_tags_comment' => 'Die Liste von Tags, welche nicht entfernt werden wenn sie keinen Inhalt haben / leer sind.', + 'allowed_tags' => 'Erlaubte Tags', 'allowed_tags_comment' => 'Die Liste von erlaubten Tags.', - 'no_wrap' => 'Tags nicht wrappen', - 'no_wrap_comment' => 'Die Liste von Tags welche nicht in Block-Tags gepackt werden sollen.', + 'allowed_attributes' => 'Erlaubte Attribute', + 'allowed_attributes_comment' => 'Die Liste von erlaubten Attributen.', + 'no_wrap' => 'Tags nicht umbrechen', + 'no_wrap_comment' => 'Die Liste von Tags, welche nicht innerhalb Block-Tags stehen sollen.', 'remove_tags' => 'Entferne Tags', 'remove_tags_comment' => 'Die Liste an Tags welche nicht zusammen entfernt werden mit ihrem Inhalt.', - 'line_breaker_tags' => 'Zeilenumbruch Tags', + 'line_breaker_tags' => 'Zeilenumbruch-Tags', 'line_breaker_tags_comment' => 'Die Liste von Tags, zwischen die ein Zeilenumbruch-Element eingefügt wird.', + 'toolbar_options' => 'Toolbar-Optionen', 'toolbar_buttons' => 'Toolbar-Buttons', - 'toolbar_buttons_comment' => 'Die Toolbar-Buttons, die im Rich Editor standardmässig angezeigt werden sollen.', + 'toolbar_buttons_comment' => 'Die Toolbar-Buttons, die im Rich-Editor standardmäßig angezeigt werden sollen.', 'toolbar_buttons_preset' => 'Standard-Vorlage für Toolbars übernehmen:', 'toolbar_buttons_presets' => [ 'default' => 'Standard', @@ -416,12 +439,12 @@ ], 'mysettings' => [ 'menu_label' => 'Meine Einstellungen', - 'menu_description' => 'Einstellungen beziehen sich auf Ihren Administratoren Account', + 'menu_description' => 'Einstellungen beziehen sich auf Ihren Administratoren-Benutzer', ], 'myaccount' => [ 'menu_label' => 'Mein Account', - 'menu_description' => 'Updaten Sie Ihre Account-Details wie z.B. den Namen, die E-Mail-Adresse und das Passwort.', - 'menu_keywords' => 'Sicheres Anmelden' + 'menu_description' => 'Aktualisieren Sie Ihre Account-Details wie z.B. den Namen, die E-Mail-Adresse und das Passwort.', + 'menu_keywords' => 'Sicheres Anmelden', ], 'branding' => [ 'menu_label' => 'Backend anpassen', @@ -430,49 +453,57 @@ 'logo' => 'Logo', 'logo_description' => 'Lade ein eigenes Logo hoch, das im Backend verwendet werden soll.', 'favicon' => 'Favicon', - 'favicon_description' => 'Laden Sie ein benutzerdefiniertes Favicon zur Verwendung im Back-End hoch', + 'favicon_description' => 'Laden Sie ein benutzerdefiniertes Favicon zur Verwendung im Backend hoch', 'app_name' => 'App-Name', 'app_name_description' => 'Dieser Name wird als Titel des Backends angezeigt.', 'app_tagline' => 'App-Tagline', - 'app_tagline_description' => 'Die Tagline wird im Log-In-Bereich des Backends angezeigt.', + 'app_tagline_description' => 'Die Tagline wird im Login-Bereich des Backends angezeigt.', 'colors' => 'Farben', + 'branding_colors' => 'Brand-Farben', + 'branding_colors_comment' => 'Diese Farben werden innerhalb des Backends verwenden um zu Ihrer Brand zu passen.', + 'default_colors' => 'Standard-Farben', + 'default_colors_comment' => 'Diese Farben werden als Farbfelder in allen Color-Pickern angezeigt, sofern nicht überschrieben.', + 'add_default_color' => 'Füge eine Standard-Farbe hinzu', 'primary_color' => 'Primärfarbe', 'secondary_color' => 'Zweitfarbe', 'accent_color' => 'Akzentfarbe', 'styles' => 'Styles', 'custom_stylesheet' => 'Benutzerdefiniertes Stylesheet', 'navigation' => 'Navigation', - 'menu_mode' => 'Menustyles', + 'menu_mode' => 'Menüstyles', 'menu_mode_inline' => 'Inline', 'menu_mode_inline_no_icons' => 'Inline (ohne Icons)', 'menu_mode_tile' => 'Tiles', - 'menu_mode_collapsed' => 'Collapsed' + 'menu_mode_collapsed' => 'Collapsed', ], 'backend_preferences' => [ - 'menu_label' => 'Backend Einstellungen', - 'menu_description' => 'Verwalten der Spracheinstellungen und der Backenddarstellung.', + 'menu_label' => 'Backend-Einstellungen', + 'menu_description' => 'Verwalten der Spracheinstellungen und der Backend-Darstellung.', 'region' => 'Region', - 'code_editor' => 'Code editor', + 'code_editor' => 'Code-Editor', 'timezone' => 'Zeitzone', - 'timezone_comment' => 'Passt die angzeigten Daten an diese Zeitzone an.', + 'timezone_comment' => 'Passt die Datumsanzeigen an diese Zeitzone an.', 'locale' => 'Sprache', 'locale_comment' => 'Wählen Sie Ihre gewünschte Sprache für das Backend.', ], 'access_log' => [ - 'hint' => 'Dieser Log zeigt eine Liste mit erfolgreichen Anmelde-Versuchen von Administratoren. Die Aufzeichnungen bleiben erhalten für :days Tage.', + 'hint' => 'Dieses Log zeigt eine Liste mit erfolgreichen Anmeldeversuchen von Administratoren. Die Aufzeichnungen bleiben erhalten für :days Tage.', 'menu_label' => 'Zugriffslog', - 'menu_description' => 'Sehen Sie sich eine Liste mit erfolgreichen Backend Benutzeranmeldungen an.', + 'menu_description' => 'Sehen Sie sich eine Liste mit erfolgreichen Benutzeranmeldungen im Backend an.', + 'id' => 'ID', 'created_at' => 'Datum & Uhrzeit', + 'type' => 'Typ', 'login' => 'Anmeldung', - 'ip_address' => 'IP Adresse', + 'ip_address' => 'IP-Adresse', 'first_name' => 'Vorname', 'last_name' => 'Nachname', 'email' => 'E-Mail', ], 'filter' => [ 'all' => 'Alle', - 'options_method_not_exists' => "Die Modelklasse :model muss eine methode :method() definiert haben und returning options for the ':filter' filter.", - 'date_all' => 'Ganzen Zeitraum' + 'options_method_not_exists' => 'Die Modelklasse :model muss eine Methode :method() definiert haben, welche die Optionen für den Filter ":filter" zurückgibt.', + 'date_all' => 'Ganzen Zeitraum', + 'number_all' => 'Alle Zahlen', ], 'import_export' => [ 'upload_csv_file' => '1. CSV-Datei hochladen', @@ -516,44 +547,46 @@ 'column_preview' => 'Spaltenvorschau', 'file_not_found_error' => 'Datei nicht gefunden', 'empty_error' => 'Es wurden keine Daten geliefert die exportiert werden können.', - 'empty_import_columns_error' => 'Bitte geben Sie einige Reihen zum importieren an.', - 'match_some_column_error' => 'Bitte Verbinden Sie erst ein paar Reihen.', + 'empty_import_columns_error' => 'Bitte geben Sie einige Spalten zum importieren an.', + 'match_some_column_error' => 'Bitte verbinden Sie erst einige Spalten.', 'required_match_column_error' => 'Bitte stellen Sie eine Verbindung zwischen den benötigten Feldern :label her.', - 'empty_export_columns_error' => 'Bitte geben Sie einige Reihen zum exportieren an.', - 'behavior_missing_uselist_error' => 'Sie müssen das Controller-Verhalten "ListController" implementieren und "useList" Option aktivieren.', - 'missing_model_class_error' => 'Bitte geben Sie die spezifische "modelClass" Eigenschaft für :type an.', - 'missing_column_id_error' => 'Fehleneder Reihen Identifier', - 'unknown_column_error' => 'Unbekannte Reihe', - 'encoding_not_supported_error' => 'Qulldatei Encoding wurde nicht bekannt oder ist nicht bekannt. Bitte wählen Sie ein Dateiformat mit ein entsprechendes Encoding um es zu importieren.', - 'encoding_format' => 'Datei encoding', + 'empty_export_columns_error' => 'Bitte geben Sie einige Spalten für den Export an.', + 'behavior_missing_uselist_error' => 'Sie müssen das Controller-Verhalten "ListController" implementieren und die "useList"-Option aktivieren.', + 'missing_model_class_error' => 'Bitte definieren Sie Eigenschaft in der Model-Klasse für :type an.', + 'missing_column_id_error' => 'Fehlenede Spaltenkennung', + 'unknown_column_error' => 'Unbekannte Spalte', + 'encoding_not_supported_error' => 'Das Encoding der Quelldatei wurde nicht erkannt. Bitte wählen Sie ein Dateiformat mit einem entsprechenden Encoding, um eine Datei zu importieren.', + 'encoding_format' => 'Datei-Encoding', 'encodings' => [ 'utf_8' => 'UTF-8', 'us_ascii' => 'US-ASCII', - 'iso_8859_1' => 'ISO-8859-1 (Latin-1, Western European)', - 'iso_8859_2' => 'ISO-8859-2 (Latin-2, Central European)', - 'iso_8859_3' => 'ISO-8859-3 (Latin-3, South European)', - 'iso_8859_4' => 'ISO-8859-4 (Latin-4, North European)', - 'iso_8859_5' => 'ISO-8859-5 (Latin, Cyrillic)', - 'iso_8859_6' => 'ISO-8859-6 (Latin, Arabic)', - 'iso_8859_7' => 'ISO-8859-7 (Latin, Greek)', - 'iso_8859_8' => 'ISO-8859-8 (Latin, Hebrew)', - 'iso_8859_9' => 'ISO-8859-9 (Latin-5, Turkish)', - 'iso_8859_10' => 'ISO-8859-10 (Latin-6, Nordic)', + 'iso_8859_1' => 'ISO-8859-1 (Latin-1, Westeuropäisch)', + 'iso_8859_2' => 'ISO-8859-2 (Latin-2, Mitteleuropäisch)', + 'iso_8859_3' => 'ISO-8859-3 (Latin-3, Südeuropäisch)', + 'iso_8859_4' => 'ISO-8859-4 (Latin-4, Nordeuropäisch)', + 'iso_8859_5' => 'ISO-8859-5 (Latin, Kyrillisch)', + 'iso_8859_6' => 'ISO-8859-6 (Latin, Arabisch)', + 'iso_8859_7' => 'ISO-8859-7 (Latin, Griechisch)', + 'iso_8859_8' => 'ISO-8859-8 (Latin, Hebräisch)', + 'iso_8859_9' => 'ISO-8859-9 (Latin-5, Türkisch)', + 'iso_8859_10' => 'ISO-8859-10 (Latin-6, Nordisch)', 'iso_8859_11' => 'ISO-8859-11 (Latin, Thai)', - 'iso_8859_13' => 'ISO-8859-13 (Latin-7, Baltic Rim)', - 'iso_8859_14' => 'ISO-8859-14 (Latin-8, Celtic)', - 'iso_8859_15' => 'ISO-8859-15 (Latin-9, Western European revision with euro sign)', + 'iso_8859_13' => 'ISO-8859-13 (Latin-7, Baltisch)', + 'iso_8859_14' => 'ISO-8859-14 (Latin-8, Keltisch)', + 'iso_8859_15' => 'ISO-8859-15 (Latin-9, Westeuropäisch: Revision mit Euro-Symbol)', + 'windows_1250' => 'Windows-1250 (CP1250, Mittel- und Osteuropäisch)', 'windows_1251' => 'Windows-1251 (CP1251)', - 'windows_1252' => 'Windows-1252 (CP1252)' - ] + 'windows_1252' => 'Windows-1252 (CP1252)', + ], ], 'permissions' => [ - 'manage_media' => 'Medien verwalten', + 'manage_media' => 'Hochladen und verwalten von Medien - Bilder, Videos, Audios, Dokumente', 'allow_unsafe_markdown' => 'Unsicheres Markdown verwenden (kann Javascript enthalten)', ], 'mediafinder' => [ 'label' => 'Media Finder', - 'default_prompt' => 'Klicke auf %s um eine Mediendatei auszuwählen' + 'default_prompt' => 'Klicke auf %s um eine Mediendatei auszuwählen', + 'no_image' => 'Das Bild konnte nicht gefunden werden', ], 'media' => [ 'menu_label' => 'Medien', @@ -573,23 +606,23 @@ 'title' => 'Titel', 'last_modified' => 'Zuletzt bearbeitet', 'public_url' => 'Öffentliche URL', - 'click_here' => 'Hier drücken', + 'click_here' => 'Hier klicken', 'thumbnail_error' => 'Fehler beim Erstellen des Thumbnails.', 'return_to_parent' => 'Zu oberem Ordner zurückkehren', - 'return_to_parent_label' => 'Stufe hoch ..', + 'return_to_parent_label' => 'Gehe hoch ..', 'nothing_selected' => 'Nichts ausgewählt.', 'multiple_selected' => 'Mehrere Dateien ausgewählt.', - 'uploading_file_num' => 'Lade :number Datei(en)...', + 'uploading_file_num' => 'Lade :number Datei(en) hoch...', 'uploading_complete' => 'Upload vollständig', 'uploading_error' => 'Upload fehlgeschlagen', 'type_blocked' => 'Der verwendete Dateityp ist aus Sicherheitsgründen gesperrt.', 'order_by' => 'Sortieren nach', - 'direction' => 'Direction', + 'direction' => 'Reihenfolge', 'direction_asc' => 'Aufsteigend', 'direction_desc' => 'Absteigend', 'folder' => 'Ordner', 'no_files_found' => 'Keine entsprechenden Dateien gefunden.', - 'delete_empty' => 'Bitte Wählen Sie Dateien zum Löschen aus.', + 'delete_empty' => 'Bitte wählen Sie Dateien zum Löschen aus.', 'delete_confirm' => 'Wollen Sie wirklich die gewählte(n) Datei(en) löschen?', 'error_renaming_file' => 'Fehler beim Umbenennen.', 'new_folder_title' => 'Neuer Ordner', @@ -605,11 +638,11 @@ 'insert' => 'Einfügen', 'crop_and_insert' => 'Zuschneiden und Einfügen', 'select_single_image' => 'Bitte wählen Sie ein einzelnes Bild.', - 'selection_not_image' => 'Die gewählte Datei ist kein Bild.', + 'selection_not_image' => 'Die gewählte Datei ist keine Bilddatei.', 'restore' => 'Alle Änderungen rückgängig machen', 'resize' => 'Größe anpassen...', 'selection_mode_normal' => 'Normal', - 'selection_mode_fixed_ratio' => 'Festes Verhältnis', + 'selection_mode_fixed_ratio' => 'Proportionen beibehalten', 'selection_mode_fixed_size' => 'Feste Größe', 'height' => 'Höhe', 'width' => 'Breite', @@ -621,5 +654,5 @@ 'rename_new_name' => 'Neuer Name', 'move_please_select' => 'Bitte auswählen', 'move_button' => 'Verschieben', - ] + ], ]; diff --git a/modules/backend/lang/el/lang.php b/modules/backend/lang/el/lang.php index acebfe19de..59fceb8c10 100644 --- a/modules/backend/lang/el/lang.php +++ b/modules/backend/lang/el/lang.php @@ -327,7 +327,7 @@ 'theme' => 'Color scheme', 'markup_styles' => 'Markup Styles', 'custom_styles' => 'Custom stylesheet', - 'custom styles_comment' => 'Custom styles to include in the HTML editor.', + 'custom_styles_comment' => 'Custom styles to include in the HTML editor.', 'markup_classes' => 'Markup Classes', 'paragraph' => 'Paragraph', 'link' => 'Link', diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php index 7b29eea022..318517f5a2 100644 --- a/modules/backend/lang/en/lang.php +++ b/modules/backend/lang/en/lang.php @@ -75,6 +75,10 @@ 'cancel' => 'Cancel', 'delete' => 'Delete', 'ok' => 'OK', + 'sending' => 'Sending...', + 'password_reset_email' => 'Send password reset email', + 'manual_password_reset_confirm' => 'Are you sure you want to send a password reset email to this user?', + 'manual_password_reset_success' => 'An email has been sent to the user with instructions to reset their password.', ], 'dashboard' => [ 'menu_label' => 'Dashboard', @@ -399,7 +403,7 @@ 'theme' => 'Color scheme', 'markup_styles' => 'Markup Styles', 'custom_styles' => 'Custom stylesheet', - 'custom styles_comment' => 'Custom styles to include in the HTML editor.', + 'custom_styles_comment' => 'Custom styles to include in the HTML editor.', 'markup_classes' => 'Markup Classes', 'paragraph' => 'Paragraph', 'link' => 'Link', diff --git a/modules/backend/lang/es/lang.php b/modules/backend/lang/es/lang.php index 71ea8de2ec..1cdc6f9eae 100644 --- a/modules/backend/lang/es/lang.php +++ b/modules/backend/lang/es/lang.php @@ -319,7 +319,7 @@ 'theme' => 'Color del esquema', 'markup_styles' => 'Estilos de marcado', 'custom_styles' => 'Hoja de estilo personalizada', - 'custom styles_comment' => 'Estilos personalizados para incluir en el editor HTML.', + 'custom_styles_comment' => 'Estilos personalizados para incluir en el editor HTML.', 'markup_classes' => 'Clases de marcado', 'paragraph' => 'Párrafo', 'link' => 'Enlace', diff --git a/modules/backend/lang/et/lang.php b/modules/backend/lang/et/lang.php index f60c4cbf59..a51d4605ab 100644 --- a/modules/backend/lang/et/lang.php +++ b/modules/backend/lang/et/lang.php @@ -339,7 +339,7 @@ 'theme' => 'Värvivalik', 'markup_styles' => 'Markup stiilid', 'custom_styles' => 'Kohandatud CSS', - 'custom styles_comment' => 'Kohandatud CSS reglid, mis lisada HTML redaktorile.', + 'custom_styles_comment' => 'Kohandatud CSS reglid, mis lisada HTML redaktorile.', 'markup_classes' => 'Markup klassid', 'paragraph' => 'Lõik', 'link' => 'Link', diff --git a/modules/backend/lang/fa/lang.php b/modules/backend/lang/fa/lang.php index 2f3e86bdfc..2398fe7020 100644 --- a/modules/backend/lang/fa/lang.php +++ b/modules/backend/lang/fa/lang.php @@ -398,7 +398,7 @@ 'theme' => 'رنگ بندی', 'markup_styles' => 'سبک نشانه گذاری', 'custom_styles' => 'شیوه نامه های سفارشی', - 'custom styles_comment' => 'شیوه نامه های سفارشی جهت وارد کردن در ویرایش گر HTML.', + 'custom_styles_comment' => 'شیوه نامه های سفارشی جهت وارد کردن در ویرایش گر HTML.', 'markup_classes' => 'کلاس های نشانه گذاری', 'paragraph' => 'پاراگراف', 'link' => 'لینک', diff --git a/modules/backend/lang/fi/lang.php b/modules/backend/lang/fi/lang.php index 7caf7fb6df..409b711aa9 100644 --- a/modules/backend/lang/fi/lang.php +++ b/modules/backend/lang/fi/lang.php @@ -357,7 +357,7 @@ 'theme' => 'Väriteema', 'markup_styles' => 'Markup-tyylit', 'custom_styles' => 'Oma tyylitiedosto', - 'custom styles_comment' => 'Omat tyylit jotka käytetään HTML-editorissa.', + 'custom_styles_comment' => 'Omat tyylit jotka käytetään HTML-editorissa.', 'markup_classes' => 'Markup-luokat', 'paragraph' => 'Kappale', 'link' => 'Linkki', diff --git a/modules/backend/lang/fr/lang.php b/modules/backend/lang/fr/lang.php index 0eb5bb982d..1c6e7ffa2e 100644 --- a/modules/backend/lang/fr/lang.php +++ b/modules/backend/lang/fr/lang.php @@ -372,7 +372,7 @@ 'theme' => 'Coloration syntaxique', 'markup_styles' => 'Styles du balisage', 'custom_styles' => 'Feuille de styles personnalisée', - 'custom styles_comment' => 'Styles personnalisés à inclure dans l\'editeur HTML.', + 'custom_styles_comment' => 'Styles personnalisés à inclure dans l\'editeur HTML.', 'markup_classes' => 'Classes de style', 'paragraph' => 'Paragraphe', 'link' => 'Lien', @@ -382,18 +382,30 @@ 'label' => 'Libellé', 'class_name' => 'Nom de la classe', 'markup_tags' => 'Balises', + 'markup_tag' => 'Balise', 'allowed_empty_tags' => 'Autoriser les balises vides', 'allowed_empty_tags_comment' => 'Liste des balises qui ne sont pas supprimées lorsqu\'elles sont vides.', 'allowed_tags' => 'Balises autorisées', 'allowed_tags_comment' => 'Liste des balises autorisées.', + 'allowed_attributes' => 'Attributs autorisés', + 'allowed_attributes_comment' => 'Liste des attributs autorisés.', 'no_wrap' => 'Balises non encadrées', 'no_wrap_comment' => 'Liste des balises qui ne doivent pas être encadrées par des balises de bloc.', 'remove_tags' => 'Balises supprimées', 'remove_tags_comment' => 'Liste des balises qui sont supprimées ainsi que leur contenu.', 'line_breaker_tags' => 'Balise de saut de ligne', 'line_breaker_tags_comment' => 'La liste des balises qui sont utilisées pour mettre des sauts de ligne.', + 'toolbar_options' => 'Options de la barre d\'outils', 'toolbar_buttons' => 'Boutons de la barre d\'outils', 'toolbar_buttons_comment' => 'Les boutons de la barre d\'outils à afficher par défaut dans l\'éditeur de texte enrichi.', + 'toolbar_buttons_preset' => 'Insérez une configuration prédéfinie des boutons de la barre d\'outils:', + 'toolbar_buttons_presets' => [ + 'default' => 'Défaut', + 'minimal' => 'Minimale', + 'full' => 'Complète', + ], + 'paragraph_formats' => 'Styles des paragraphes', + 'paragraph_formats_comment' => 'Les options qui apparaîtrons dans la liste déroulante des styles de paragraphe.', ], 'tooltips' => [ 'preview_website' => 'Aperçu du site' diff --git a/modules/backend/lang/hu/lang.php b/modules/backend/lang/hu/lang.php index f1b3f15cdf..5b4978ede4 100644 --- a/modules/backend/lang/hu/lang.php +++ b/modules/backend/lang/hu/lang.php @@ -397,7 +397,7 @@ 'theme' => 'Színséma', 'markup_styles' => 'Stílusok', 'custom_styles' => 'Egyéni megjelenés', - 'custom styles_comment' => 'Saját stílusok és megjelenések megadása.', + 'custom_styles_comment' => 'Saját stílusok és megjelenések megadása.', 'markup_classes' => 'Értékek', 'paragraph' => 'Bekezdés', 'link' => 'Hivatkozás', diff --git a/modules/backend/lang/it/lang.php b/modules/backend/lang/it/lang.php index 0bc6974a86..7d1f3f7fd5 100644 --- a/modules/backend/lang/it/lang.php +++ b/modules/backend/lang/it/lang.php @@ -357,7 +357,7 @@ 'theme' => 'Schema di colori', 'markup_styles' => 'Stili di markup', 'custom_styles' => 'Foglio di stile personalizzato', - 'custom styles_comment' => 'Stili personalizzati da includere nell\'editor HTML.', + 'custom_styles_comment' => 'Stili personalizzati da includere nell\'editor HTML.', 'markup_classes' => 'Classi di markup', 'paragraph' => 'Paragrafo', 'link' => 'Collegamento', diff --git a/modules/backend/lang/ja/lang.php b/modules/backend/lang/ja/lang.php index e81b0a53ab..264e27e02a 100644 --- a/modules/backend/lang/ja/lang.php +++ b/modules/backend/lang/ja/lang.php @@ -400,7 +400,7 @@ 'theme' => 'カラーテーマ', 'markup_styles' => 'マークアップ・スタイル', 'custom_styles' => 'カスタムスタイルシート', - 'custom styles_comment' => 'HTMLエディタに含めるカスタムスタイル', + 'custom_styles_comment' => 'HTMLエディタに含めるカスタムスタイル', 'markup_classes' => 'マークアップクラス', 'paragraph' => '段落', 'link' => 'リンク', @@ -434,7 +434,7 @@ ], 'paragraph_formats' => '段落の書式', 'paragraph_formats_comment' => '段落形式のドロップダウンに表示されるオプション', - + ], 'tooltips' => [ 'preview_website' => 'Webサイトをプレビューする', diff --git a/modules/backend/lang/kr/lang.php b/modules/backend/lang/kr/lang.php index df63f138d0..825845eefe 100644 --- a/modules/backend/lang/kr/lang.php +++ b/modules/backend/lang/kr/lang.php @@ -338,7 +338,7 @@ 'theme' => '색상 스키마', 'markup_styles' => '마크업 스타일', 'custom_styles' => '별도의 스타일시트', - 'custom styles_comment' => '에디터에 별도의 스타일시트를 포함시킨다.', + 'custom_styles_comment' => '에디터에 별도의 스타일시트를 포함시킨다.', 'markup_classes' => '마크업 클래스', 'paragraph' => '단락', 'link' => '링크', diff --git a/modules/backend/lang/lt/lang.php b/modules/backend/lang/lt/lang.php index 4e5dd3a609..012c0d5256 100644 --- a/modules/backend/lang/lt/lang.php +++ b/modules/backend/lang/lt/lang.php @@ -336,7 +336,7 @@ 'theme' => 'Spalvų schema', 'markup_styles' => 'Markup Styles', 'custom_styles' => 'Custom stylesheet', - 'custom styles_comment' => 'Custom styles to include in the HTML editor.', + 'custom_styles_comment' => 'Custom styles to include in the HTML editor.', 'markup_classes' => 'Žymėjimo Klasės', 'paragraph' => 'Pastraipa', 'link' => 'Nuoroda', diff --git a/modules/backend/lang/lv/lang.php b/modules/backend/lang/lv/lang.php index 9904321322..e664297ab2 100644 --- a/modules/backend/lang/lv/lang.php +++ b/modules/backend/lang/lv/lang.php @@ -399,7 +399,7 @@ 'theme' => 'Krāsu shēma', 'markup_styles' => 'Iezīmēšanas stili', 'custom_styles' => 'Pielāgota stila lapa', - 'custom styles_comment' => 'Pielāgotie stili, kurus iekļaut HTML redaktorā.', + 'custom_styles_comment' => 'Pielāgotie stili, kurus iekļaut HTML redaktorā.', 'markup_classes' => 'Iezīmēšanas klases', 'paragraph' => 'Rindkopa', 'link' => 'Saite', diff --git a/modules/backend/lang/nb-no/lang.php b/modules/backend/lang/nb-no/lang.php index 993a3c3150..7c05e8a290 100644 --- a/modules/backend/lang/nb-no/lang.php +++ b/modules/backend/lang/nb-no/lang.php @@ -327,7 +327,7 @@ 'theme' => 'Fargetema', 'markup_styles' => 'Markup-stiler', 'custom_styles' => 'Tilpasset stilsett (CSS)', - 'custom styles_comment' => 'Tilpassede CSS-stilregler å inkludere i HTML-editoren.', + 'custom_styles_comment' => 'Tilpassede CSS-stilregler å inkludere i HTML-editoren.', 'markup_classes' => 'Markup-klasser', 'paragraph' => 'Avsnitt', 'link' => 'Link', diff --git a/modules/backend/lang/nl/lang.php b/modules/backend/lang/nl/lang.php index b53ca43897..0db41eca25 100644 --- a/modules/backend/lang/nl/lang.php +++ b/modules/backend/lang/nl/lang.php @@ -397,7 +397,7 @@ 'theme' => 'Kleurschema', 'markup_styles' => 'Opmaakstijlen', 'custom_styles' => 'Eigen stylesheet', - 'custom styles_comment' => 'Eigen stijlen die in de HTML-editor gebruikt moeten worden.', + 'custom_styles_comment' => 'Eigen stijlen die in de HTML-editor gebruikt moeten worden.', 'markup_classes' => 'Opmaak classes', 'paragraph' => 'Paragraaf', 'link' => 'Link', diff --git a/modules/backend/lang/pl/lang.php b/modules/backend/lang/pl/lang.php index 284076f69c..c173d4e9d1 100644 --- a/modules/backend/lang/pl/lang.php +++ b/modules/backend/lang/pl/lang.php @@ -390,7 +390,7 @@ 'theme' => 'Schemat kolorów', 'markup_styles' => 'Style znaczników', 'custom_styles' => 'Niestandardowy arkusz stylów', - 'custom styles_comment' => 'Niestandardowe style do dołączenia w edytorze HTML.', + 'custom_styles_comment' => 'Niestandardowe style do dołączenia w edytorze HTML.', 'markup_classes' => 'Klasy znaczników', 'paragraph' => 'Paragraf', 'link' => 'Link', diff --git a/modules/backend/lang/pt-br/lang.php b/modules/backend/lang/pt-br/lang.php index f0c372d24a..0a3633c308 100644 --- a/modules/backend/lang/pt-br/lang.php +++ b/modules/backend/lang/pt-br/lang.php @@ -397,7 +397,7 @@ 'theme' => 'Esquema de cores', 'markup_styles' => 'Estilos de marcação', 'custom_styles' => 'Folha de estilo personalizada', - 'custom styles_comment' => 'Estilos personalizados para incluir no editor HTML.', + 'custom_styles_comment' => 'Estilos personalizados para incluir no editor HTML.', 'markup_classes' => 'Classes de marcação', 'paragraph' => 'Parágrafo', 'link' => 'Link', diff --git a/modules/backend/lang/pt-pt/lang.php b/modules/backend/lang/pt-pt/lang.php index f9e84ca522..f84136c748 100644 --- a/modules/backend/lang/pt-pt/lang.php +++ b/modules/backend/lang/pt-pt/lang.php @@ -390,7 +390,7 @@ 'theme' => 'Esquema de cores', 'markup_styles' => 'Estilos de marcação', 'custom_styles' => 'Folha de estilo personalizada', - 'custom styles_comment' => 'Estilos personalizados para incluir no editor HTML.', + 'custom_styles_comment' => 'Estilos personalizados para incluir no editor HTML.', 'markup_classes' => 'Classes de marcação', 'paragraph' => 'Parágrafo', 'link' => 'Ligação', diff --git a/modules/backend/lang/ro/lang.php b/modules/backend/lang/ro/lang.php index 0d42a5076d..d9484dbaf4 100644 --- a/modules/backend/lang/ro/lang.php +++ b/modules/backend/lang/ro/lang.php @@ -397,7 +397,7 @@ 'theme' => 'Schema de culori', 'markup_styles' => 'Stiluri de marcare', 'custom_styles' => 'Foaie de stil personalizată', - 'custom styles_comment' => 'Stiluri personalizate de inclus în editorul HTML.', + 'custom_styles_comment' => 'Stiluri personalizate de inclus în editorul HTML.', 'markup_classes' => 'Clase de marcare', 'paragraph' => 'Paragraf', 'link' => 'Legătură', diff --git a/modules/backend/lang/rs/lang.php b/modules/backend/lang/rs/lang.php index 41e3d9920d..bd7026c0c7 100644 --- a/modules/backend/lang/rs/lang.php +++ b/modules/backend/lang/rs/lang.php @@ -395,7 +395,7 @@ 'theme' => 'Boje', 'markup_styles' => 'Stilovi označavanja', 'custom_styles' => 'Proizvoljni stilovi', - 'custom styles_comment' => 'Proizvoljni stilovi za uključivanje u HTML editor.', + 'custom_styles_comment' => 'Proizvoljni stilovi za uključivanje u HTML editor.', 'markup_classes' => 'Klase označavanja', 'paragraph' => 'Paragraf', 'link' => 'Link', diff --git a/modules/backend/lang/ru/lang.php b/modules/backend/lang/ru/lang.php index 057f83fee4..e09e4dce6a 100644 --- a/modules/backend/lang/ru/lang.php +++ b/modules/backend/lang/ru/lang.php @@ -399,7 +399,7 @@ 'theme' => 'Цветовая схема', 'markup_styles' => 'Стили разметки', 'custom_styles' => 'Дополнительные CSS стили', - 'custom styles_comment' => 'Дополнительные стили для использования в HTML редакторе.', + 'custom_styles_comment' => 'Дополнительные стили для использования в HTML редакторе.', 'markup_classes' => 'Классы разметки', 'paragraph' => 'Параграф', 'link' => 'Ссылка', diff --git a/modules/backend/lang/sk/lang.php b/modules/backend/lang/sk/lang.php index 3a33d3378e..3982fc27e9 100644 --- a/modules/backend/lang/sk/lang.php +++ b/modules/backend/lang/sk/lang.php @@ -363,7 +363,7 @@ 'theme' => 'Farebná schéma', 'markup_styles' => 'Štýly', 'custom_styles' => 'Vlastné štýly', - 'custom styles_comment' => 'Vlastné štýly, ktoré budú zahrnuté do editora HTML.', + 'custom_styles_comment' => 'Vlastné štýly, ktoré budú zahrnuté do editora HTML.', 'markup_classes' => 'Triedy štýlov', 'paragraph' => 'Odstavec', 'link' => 'Odkaz', diff --git a/modules/backend/lang/sl/lang.php b/modules/backend/lang/sl/lang.php index 97bfb057ca..44324b2e02 100644 --- a/modules/backend/lang/sl/lang.php +++ b/modules/backend/lang/sl/lang.php @@ -396,7 +396,7 @@ 'theme' => 'Barvna shema', 'markup_styles' => 'Označevalni slogi', 'custom_styles' => 'Slog po meri', - 'custom styles_comment' => 'Slogi, ki jih želite vključiti v urejevalnik HTML.', + 'custom_styles_comment' => 'Slogi, ki jih želite vključiti v urejevalnik HTML.', 'markup_classes' => 'Označevalni razredi', 'paragraph' => 'Odstavek', 'link' => 'Povezava', diff --git a/modules/backend/lang/th/lang.php b/modules/backend/lang/th/lang.php index 1f60e919f4..ba19fab3e4 100644 --- a/modules/backend/lang/th/lang.php +++ b/modules/backend/lang/th/lang.php @@ -346,7 +346,7 @@ 'theme' => 'แผนผังสี', 'markup_styles' => 'รูปแบบ', 'custom_styles' => 'กำหนด stylesheet เอง', - 'custom styles_comment' => 'รูปแบบกำหนดเองที่จะเพิ่มในตัวแก้ไข HTML', + 'custom_styles_comment' => 'รูปแบบกำหนดเองที่จะเพิ่มในตัวแก้ไข HTML', 'markup_classes' => 'คลาส', 'paragraph' => 'ย่อหน้า', 'link' => 'ลิงก์', diff --git a/modules/backend/lang/tr/lang.php b/modules/backend/lang/tr/lang.php index 4918db495c..6ae7bbdc7b 100644 --- a/modules/backend/lang/tr/lang.php +++ b/modules/backend/lang/tr/lang.php @@ -371,7 +371,7 @@ 'theme' => 'Renk şeması', 'markup_styles' => 'Markup Stilleri', 'custom_styles' => 'Özel CSS', - 'custom styles_comment' => 'HTML editöre uygulanacak özel stiller.', + 'custom_styles_comment' => 'HTML editöre uygulanacak özel stiller.', 'markup_classes' => 'Markup Classlar', 'paragraph' => 'Paragraf', 'link' => 'Link', diff --git a/modules/backend/lang/uk/lang.php b/modules/backend/lang/uk/lang.php index 2f650899cd..d0b3928888 100644 --- a/modules/backend/lang/uk/lang.php +++ b/modules/backend/lang/uk/lang.php @@ -399,7 +399,7 @@ 'theme' => 'Кольорова схема', 'markup_styles' => 'Стилі розмітки', 'custom_styles' => 'Спеціальна таблиця стилів', - 'custom styles_comment' => 'Спеціальні стилі для включення в редактор HTML.', + 'custom_styles_comment' => 'Спеціальні стилі для включення в редактор HTML.', 'markup_classes' => 'Класи розмітки', 'paragraph' => 'Абзац', 'link' => 'Посилання', diff --git a/modules/backend/lang/vn/lang.php b/modules/backend/lang/vn/lang.php index 5041660e8e..0ee56f4c75 100644 --- a/modules/backend/lang/vn/lang.php +++ b/modules/backend/lang/vn/lang.php @@ -357,7 +357,7 @@ 'theme' => 'Color scheme', 'markup_styles' => 'Markup Styles', 'custom_styles' => 'Stylesheet tùy chỉnh', - 'custom styles_comment' => 'Styles tùy chỉnh được thêm vào HTML editor.', + 'custom_styles_comment' => 'Styles tùy chỉnh được thêm vào HTML editor.', 'markup_classes' => 'Markup Classes', 'paragraph' => 'Paragraph', 'link' => 'Link', @@ -565,7 +565,7 @@ 'please_select_move_dest' => 'Chọn nơi mà file hoặc thư mục cần chuyển đến.', 'move_dest_src_match' => 'Chọn thư mục khác.', 'empty_library' => 'Thư mục trống.Vui lòng tải tệp tin lên hoặc tạo thư mục mới để bắt đầu.', - 'insert' => 'Chàn vào', + 'insert' => 'Chèn vào', 'crop_and_insert' => 'Cắt & Chèn vào', 'select_single_image' => 'vui lòng chọn một hình ảnh.', 'selection_not_image' => 'Mục đã chọn không phải là hình ảnh.', diff --git a/modules/backend/lang/zh-cn/lang.php b/modules/backend/lang/zh-cn/lang.php index 3a1e214423..d5ad451b6a 100644 --- a/modules/backend/lang/zh-cn/lang.php +++ b/modules/backend/lang/zh-cn/lang.php @@ -382,7 +382,7 @@ 'theme' => '色彩主题', 'markup_styles' => '标记样式', 'custom_styles' => '定制样式表', - 'custom styles_comment' => '在HTML编辑器中包含自定义样式', + 'custom_styles_comment' => '在HTML编辑器中包含自定义样式', 'markup_classes' => '标记类', 'paragraph' => '段落', 'link' => '链接', diff --git a/modules/backend/models/ExportModel.php b/modules/backend/models/ExportModel.php index 21f5a658f7..7a1b457889 100644 --- a/modules/backend/models/ExportModel.php +++ b/modules/backend/models/ExportModel.php @@ -63,7 +63,7 @@ public function download($name, $outputName = null) throw new ApplicationException(Lang::get('backend::lang.import_export.file_not_found_error')); } - return Response::download($csvPath, $outputName)->deleteFileAfterSend(true); + return Response::download($csvPath, $outputName, ['Content-Type' => 'text/csv'])->deleteFileAfterSend(true); } /** diff --git a/modules/backend/models/UserPreference.php b/modules/backend/models/UserPreference.php index f8287e601f..be97c62dc4 100644 --- a/modules/backend/models/UserPreference.php +++ b/modules/backend/models/UserPreference.php @@ -29,9 +29,6 @@ class UserPreference extends PreferencesBase public function resolveUser($user) { $user = BackendAuth::getUser(); - if (!$user) { - throw new SystemException(trans('backend::lang.user.preferences.not_authenticated')); - } return $user; } diff --git a/modules/backend/models/editorsetting/fields.yaml b/modules/backend/models/editorsetting/fields.yaml index 179e3889bb..d144981253 100644 --- a/modules/backend/models/editorsetting/fields.yaml +++ b/modules/backend/models/editorsetting/fields.yaml @@ -7,7 +7,7 @@ tabs: html_custom_styles: label: backend::lang.editor.custom_styles - commentAbove: backend::lang.editor.custom styles_comment + commentAbove: backend::lang.editor.custom_styles_comment tab: backend::lang.editor.markup_styles type: codeeditor size: giant diff --git a/modules/backend/models/user/fields.yaml b/modules/backend/models/user/fields.yaml index bbfbae286f..8b34fb476d 100644 --- a/modules/backend/models/user/fields.yaml +++ b/modules/backend/models/user/fields.yaml @@ -68,11 +68,15 @@ tabs: secondaryTabs: fields: btn_impersonate: - label: '' + label: "" context: [update] type: partial btn_unsuspend: - label: '' + label: "" + context: [update] + type: partial + btn_password_reset: + label: "" context: [update] type: partial avatar: diff --git a/modules/backend/phpunit.xml b/modules/backend/phpunit.xml index 20888c41d4..7c0631aa89 100644 --- a/modules/backend/phpunit.xml +++ b/modules/backend/phpunit.xml @@ -1,22 +1,17 @@ - ./tests - - - - - diff --git a/modules/backend/tests/models/ExportModelTest.php b/modules/backend/tests/models/ExportModelTest.php index 4c1d5e8e7a..1c110eccad 100644 --- a/modules/backend/tests/models/ExportModelTest.php +++ b/modules/backend/tests/models/ExportModelTest.php @@ -65,11 +65,13 @@ public function testDownload() $response->prepare($request); $this->assertTrue($response->headers->has('Content-Type'), "Response is missing the Content-Type header!"); + + $contentType = $response->headers->get('Content-Type'); $this->assertTrue( - $response->headers->contains('Content-Type', 'application/csv') - || $response->headers->contains('Content-Type', 'text/plain') - || $response->headers->contains('Content-Type', 'text/csv'), - "Content-Type is not as expected, provided: " . $response->headers->get('Content-Type') + str_contains($contentType, 'application/csv') + || str_contains($contentType, 'text/plain') + || str_contains($contentType, 'text/csv'), + "Content-Type is not as expected, provided: " . $contentType ); ob_start(); diff --git a/modules/backend/traits/FormModelWidget.php b/modules/backend/traits/FormModelWidget.php index d53a0d6afb..5da7cc1d90 100644 --- a/modules/backend/traits/FormModelWidget.php +++ b/modules/backend/traits/FormModelWidget.php @@ -41,7 +41,7 @@ public function resolveModelAttribute($attribute) * supports nesting via HTML array. * @return Relation */ - protected function getRelationModel() + public function getRelationModel() { list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom); diff --git a/modules/backend/traits/UploadableWidget.php b/modules/backend/traits/UploadableWidget.php index 0ee1b43c33..dd1e12a588 100644 --- a/modules/backend/traits/UploadableWidget.php +++ b/modules/backend/traits/UploadableWidget.php @@ -3,10 +3,14 @@ use Str; use File; use Lang; +use Event; +use Config; +use Storage; use Request; use Response; use ApplicationException; use System\Classes\MediaLibrary; +use Illuminate\Filesystem\FilesystemAdapter; use Winter\Storm\Filesystem\Definitions as FileDefinitions; /** @@ -23,76 +27,104 @@ trait UploadableWidget // */ // public $uploadPath; + /** + * Returns the disk that will be used to store the uploaded file + */ + public function uploadableGetDisk(): FilesystemAdapter + { + return MediaLibrary::instance()->getStorageDisk(); + } + + /** + * Returns the path on the disk to store the uploaded file + */ + public function uploadableGetUploadPath(string $fileName): string + { + // Use the configured upload path unless it's null, in which case use the user-provided path + $path = !empty($this->uploadPath) ? $this->uploadPath : Request::input('path'); + $path = MediaLibrary::validatePath($path); + $path = MediaLibrary::instance()->getMediaPath($path); + $filePath = rtrim($path, '/') . '/' . $fileName; + return $filePath; + } + + /** + * Returns the URL to the uploaded file + * + * @TODO: Replace cms.storage system with real disks + */ + public function uploadableGetUploadUrl(string $diskPath): string + { + // Get the media folder + $storageFolder = MediaLibrary::instance()->getMediaPath(''); + + // Remove the media folder from the provided disk path since it already has it + $url = MediaLibrary::url(Str::after($diskPath, $storageFolder)); + + return $url; + } + /** * Process file uploads submitted via AJAX * - * @return void * @throws ApplicationException If the file "file_data" wasn't detected in the request or if the file failed to pass validation / security checks */ - public function onUpload() + public function onUpload(): ?\Illuminate\Http\Response { if ($this->readOnly) { - return; + return null; } - try { - if (!Request::hasFile('file_data')) { - throw new ApplicationException('File missing from request'); - } - - $uploadedFile = Request::file('file_data'); + /** + * @event backend.widgets.uploadable.onUpload + * Provides an opportunity to process the file upload using custom logic. + * + * Example usage () + */ + if ($result = Event::fire('backend.widgets.uploadable.onUpload', [$this], true)) { + return $result; + } - $fileName = $uploadedFile->getClientOriginalName(); + return $this->onUploadDirect(); + } - /* - * Convert uppcare case file extensions to lower case - */ - $extension = strtolower($uploadedFile->getClientOriginalExtension()); - $fileName = File::name($fileName).'.'.$extension; + protected function onUploadDirect(): \Illuminate\Http\Response + { + if (!Request::hasFile('file_data')) { + throw new ApplicationException('File missing from request'); + } - /* - * File name contains non-latin characters, attempt to slug the value - */ - if (!$this->validateFileName($fileName)) { - $fileNameClean = $this->cleanFileName(File::name($fileName)); - $fileName = $fileNameClean . '.' . $extension; - } + try { + $uploadedFile = Request::file('file_data'); - /* - * Check for unsafe file extensions - */ - if (!$this->validateFileType($fileName)) { - throw new ApplicationException(Lang::get('backend::lang.media.type_blocked')); - } + $fileName = $this->validateMediaFileName( + $uploadedFile->getClientOriginalName(), + $uploadedFile->getClientOriginalExtension() + ); /* * See mime type handling in the asset manager */ if (!$uploadedFile->isValid()) { if ($uploadedFile->getError() === UPLOAD_ERR_OK) { - $message = "The file \"{$uploadedFile->getClientOriginalName()}\" uploaded successfully but wasn't available at {$uploadedFile->getPathName()}. Check to make sure that nothing moved it away."; + $message = "The file \"{$uploadedFile->getClientOriginalName()}\" uploaded successfully but wasn't " + . "available at {$uploadedFile->getPathName()}. Check to make sure that nothing moved it away."; } else { $message = $uploadedFile->getErrorMessage(); } throw new ApplicationException($message); } - // Use the configured upload path unless it's null, in which case use the user-provided path - $path = !empty($this->uploadPath) ? $this->uploadPath : Request::input('path'); - $path = MediaLibrary::validatePath($path); - $filePath = rtrim($path, '/') . '/' . $fileName; - /* * getRealPath() can be empty for some environments (IIS) */ - $realPath = empty(trim($uploadedFile->getRealPath())) + $sourcePath = empty(trim($uploadedFile->getRealPath())) ? $uploadedFile->getPath() . DIRECTORY_SEPARATOR . $uploadedFile->getFileName() : $uploadedFile->getRealPath(); - MediaLibrary::instance()->put( - $filePath, - File::get($realPath) - ); + $filePath = $this->uploadableGetUploadPath($fileName); + + $this->uploadableGetDisk()->put($filePath, File::get($sourcePath)); /** * @event media.file.upload @@ -114,7 +146,7 @@ public function onUpload() $this->fireSystemEvent('media.file.upload', [&$filePath, $uploadedFile]); $response = Response::make([ - 'link' => MediaLibrary::url($filePath), + 'link' => $this->uploadableGetUploadUrl($filePath), 'result' => 'success' ]); } catch (\Exception $ex) { @@ -124,13 +156,38 @@ public function onUpload() return $response; } + public function validateMediaFileName(string $fileName, string $extension): string + { + /* + * Convert uppcare case file extensions to lower case + */ + $extension = strtolower($extension); + $fileName = File::name($fileName).'.'.$extension; + + /* + * File name contains non-latin characters, attempt to slug the value + */ + if (!$this->validateFileName($fileName)) { + $fileName = $this->cleanFileName(File::name($fileName)) . '.' . $extension; + } + + /* + * Check for unsafe file extensions + */ + if (!$this->validateFileType($fileName)) { + throw new ApplicationException(Lang::get('backend::lang.media.type_blocked')); + } + + return $fileName; + } + /** * Validate a proposed media item file name. * * @param string * @return bool */ - protected function validateFileName($name) + protected function validateFileName($name): bool { if (!preg_match('/^[\w@\.\s_\-]+$/iu', $name)) { return false; @@ -149,7 +206,7 @@ protected function validateFileName($name) * @param string * @return bool */ - protected function validateFileType($name) + protected function validateFileType($name): bool { $extension = strtolower(File::extension($name)); diff --git a/modules/backend/widgets/Form.php b/modules/backend/widgets/Form.php index 494f019982..8691e5ad85 100644 --- a/modules/backend/widgets/Form.php +++ b/modules/backend/widgets/Form.php @@ -358,20 +358,15 @@ public function onRefresh() /** * @event backend.form.beforeRefresh - * Called before the form is refreshed, modify the $dataHolder->data property in place + * Called before the form is refreshed. * - * Example usage: - * - * Event::listen('backend.form.beforeRefresh', function ((\Backend\Widgets\Form) $formWidget, (stdClass) $dataHolder) { - * $dataHolder->data = $arrayOfSaveDataToReplaceExistingDataWith; - * }); - * - * Or - * - * $formWidget->bindEvent('form.beforeRefresh', function ((stdClass) $dataHolder) { - * $dataHolder->data = $arrayOfSaveDataToReplaceExistingDataWith; - * }); + * This allows you to modify the form data before the form is refreshed. * + * @param \Backend\Widgets\Form $formWidget The form widget instance. If the event is attached directly to the form widget, this + * parameter will be omitted. + * @param \stdClass $dataHolder An object containing the data from the form to be saved. It contains one property, `data`, with the array of + * form data stored within. + * @local-event $formWidget form.beforeRefresh Attached to a form widget instance. */ $dataHolder = (object) ['data' => $saveData]; $this->fireSystemEvent('backend.form.beforeRefresh', [$dataHolder]); @@ -1279,7 +1274,7 @@ protected function applyFiltersFromModel() * @param $fieldOptions * @return mixed */ - protected function getOptionsFromModel($field, $fieldOptions) + public function getOptionsFromModel($field, $fieldOptions) { /* * Advanced usage, supplied options are callable diff --git a/modules/backend/widgets/Lists.php b/modules/backend/widgets/Lists.php index 0e551f54dd..dc9e181254 100644 --- a/modules/backend/widgets/Lists.php +++ b/modules/backend/widgets/Lists.php @@ -392,7 +392,11 @@ public function prepareQuery() $relationSearchable = []; $columnsToSearch = []; - if (!empty($this->searchTerm) && ($searchableColumns = $this->getSearchableColumns())) { + if ( + strlen($this->searchTerm) !== 0 + && trim($this->searchTerm) !== '' + && ($searchableColumns = $this->getSearchableColumns()) + ) { foreach ($searchableColumns as $column) { /* * Related @@ -510,7 +514,13 @@ public function prepareQuery() ? DbDongle::raw("group_concat(" . $sqlSelect . " separator ', ')") : DbDongle::raw($sqlSelect); - $joinSql = $countQuery->select($joinSql)->toSql(); + $joinQuery = $countQuery->select($joinSql); + + if (!empty($column->config['conditions'])) { + $joinQuery->whereRaw(DbDongle::parse($column->config['conditions'])); + } + + $joinSql = $joinQuery->toSql(); $selects[] = Db::raw("(".$joinSql.") as ".$alias); @@ -1468,7 +1478,10 @@ public function addFilter(callable $filter) */ public function setSearchTerm($term, $resetPagination = false) { - if (!empty($term)) { + if ( + strlen($this->searchTerm) !== 0 + && trim($this->searchTerm) !== '' + ) { $this->showTree = false; } diff --git a/modules/backend/widgets/MediaManager.php b/modules/backend/widgets/MediaManager.php index 71eb09875a..6a5070511a 100644 --- a/modules/backend/widgets/MediaManager.php +++ b/modules/backend/widgets/MediaManager.php @@ -3,6 +3,7 @@ use Str; use Lang; use Input; +use Event; use Config; use Backend; use ApplicationException; @@ -352,7 +353,7 @@ public function onDeleteItem(): array /** * Show rename item popup AJAX handler */ - public function onLoadRenamePopup(): array + public function onLoadRenamePopup(): string { $this->abortIfReadOnly(); @@ -373,7 +374,7 @@ public function onLoadRenamePopup(): array * @throws ApplicationException if the new name is invalid * @todo Move media events to the MediaLibary class instead. */ - public function onApplyName(): array + public function onApplyName(): void { $this->abortIfReadOnly(); @@ -675,11 +676,15 @@ public function onLoadImageCropPopup(): string $path = Input::get('path'); $path = MediaLibrary::validatePath($path); $selectionParams = $this->getSelectionParams(); - $url = MediaLibrary::url($path); - $dimensions = Str::startsWith($url, '/') - ? getimagesize(base_path($url)) - : getimagesize($url); + + // @TODO: Improve support non-local disks + if (Str::startsWith($url, '/')) { + $localPath = base_path(implode("/", array_map("rawurldecode", explode("/", $url)))); + $dimensions = getimagesize($localPath); + } else { + $dimensions = getimagesize($url); + } $width = $dimensions[0]; $height = $dimensions[1] ?: 1; @@ -1215,7 +1220,7 @@ protected function generateThumbnail($thumbnailInfo, $thumbnailParams = null): a return [ 'id' => $id, 'markup' => $this->makePartial('thumbnail-image', [ - 'imageUrl' => MediaLibary::url($thumbnailInfo['path']), + 'imageUrl' => MediaLibrary::url($thumbnailInfo['path']), ]), ]; } diff --git a/modules/backend/widgets/filter/partials/_scope_numberrange.php b/modules/backend/widgets/filter/partials/_scope_numberrange.php index 4cad0ee188..c9c3502ff7 100644 --- a/modules/backend/widgets/filter/partials/_scope_numberrange.php +++ b/modules/backend/widgets/filter/partials/_scope_numberrange.php @@ -13,4 +13,3 @@ class="filter-scope-number filter-has-popover range label)) ?>: -0 \ No newline at end of file diff --git a/modules/backend/widgets/form/partials/_field_range.php b/modules/backend/widgets/form/partials/_field_range.php new file mode 100644 index 0000000000..77f774821b --- /dev/null +++ b/modules/backend/widgets/form/partials/_field_range.php @@ -0,0 +1,40 @@ + +previewMode): ?> + value) ? e($field->value) : ' ' ?> + + config['min'] ?? 0; + $max = $field->config['max'] ?? 100; + $step = $field->config['step'] ?? 1; + $value = $field->value; + if ($min > $max) { + $min = $max - $step; + } + if (is_null($value)) { + $value = ($min + $max) / 2; + } + ?> + + getAttributes() ?> + /> + + + diff --git a/modules/backend/widgets/form/partials/_field_switch.php b/modules/backend/widgets/form/partials/_field_switch.php index d68ad7148e..cd176e122c 100644 --- a/modules/backend/widgets/form/partials/_field_switch.php +++ b/modules/backend/widgets/form/partials/_field_switch.php @@ -10,7 +10,7 @@
- + comment): ?>

commentHtml ? trans($field->comment) : e(trans($field->comment)) ?>

diff --git a/modules/backend/widgets/form/partials/_field_text.php b/modules/backend/widgets/form/partials/_field_text.php index ab89423624..04a1e5433b 100644 --- a/modules/backend/widgets/form/partials/_field_text.php +++ b/modules/backend/widgets/form/partials/_field_text.php @@ -10,7 +10,6 @@ placeholder="placeholder)) ?>" class="form-control" autocomplete="off" - hasAttribute('maxlength') ? '' : 'maxlength="255"' ?> getAttributes() ?> /> diff --git a/modules/backend/widgets/mediamanager/assets/js/mediamanager-browser-min.js b/modules/backend/widgets/mediamanager/assets/js/mediamanager-browser-min.js index 3088fafe52..90583bc335 100644 --- a/modules/backend/widgets/mediamanager/assets/js/mediamanager-browser-min.js +++ b/modules/backend/widgets/mediamanager/assets/js/mediamanager-browser-min.js @@ -215,7 +215,8 @@ this.dropzone.on('totaluploadprogress',this.proxy(this.uploadUpdateTotalProgress this.dropzone.on('queuecomplete',this.proxy(this.uploadQueueComplete)) this.dropzone.on('sending',this.proxy(this.uploadSending)) this.dropzone.on('error',this.proxy(this.uploadError)) -this.dropzone.on('success',this.proxy(this.uploadSuccess))} +this.dropzone.on('success',this.proxy(this.uploadSuccess)) +Snowboard.globalEvent("widgets.mediamanager.initUploader",this);} MediaManager.prototype.destroyUploader=function(){if(!this.dropzone)return this.dropzone.destroy() this.dropzone=null} diff --git a/modules/backend/widgets/mediamanager/assets/js/mediamanager.js b/modules/backend/widgets/mediamanager/assets/js/mediamanager.js index 7c64e47dfc..a45a898167 100644 --- a/modules/backend/widgets/mediamanager/assets/js/mediamanager.js +++ b/modules/backend/widgets/mediamanager/assets/js/mediamanager.js @@ -736,6 +736,8 @@ this.dropzone.on('sending', this.proxy(this.uploadSending)) this.dropzone.on('error', this.proxy(this.uploadError)) this.dropzone.on('success', this.proxy(this.uploadSuccess)) + + Snowboard.globalEvent("widgets.mediamanager.initUploader", this); } MediaManager.prototype.destroyUploader = function() { diff --git a/modules/backend/widgets/mediamanager/partials/_crop-toolbar.php b/modules/backend/widgets/mediamanager/partials/_crop-toolbar.php index c1c2f46de7..ebcb0f530f 100644 --- a/modules/backend/widgets/mediamanager/partials/_crop-toolbar.php +++ b/modules/backend/widgets/mediamanager/partials/_crop-toolbar.php @@ -28,10 +28,10 @@ - /> + /> - /> + /> diff --git a/modules/cms/LICENSE b/modules/cms/LICENSE new file mode 100644 index 0000000000..7b47a3b139 --- /dev/null +++ b/modules/cms/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2013-2021.03.01 October CMS +Copyright (c) 2021 Winter CMS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/modules/cms/README.md b/modules/cms/README.md new file mode 100644 index 0000000000..5f804cccc7 --- /dev/null +++ b/modules/cms/README.md @@ -0,0 +1,5 @@ +# Winter CMS - CMS Module + +This repository is a read-only sub-split of the Winter CMS `Cms` module for use in Composer. Please note that we do not accept any pull requests to this repository. + +If you wish to make changes to this module, please submit them to the [main repository](https://github.com/wintercms/winter). diff --git a/modules/cms/ServiceProvider.php b/modules/cms/ServiceProvider.php index 082ad6670d..7d8e6fd6eb 100644 --- a/modules/cms/ServiceProvider.php +++ b/modules/cms/ServiceProvider.php @@ -94,7 +94,7 @@ protected function registerConsole() protected function registerTwigParser() { // Register CMS Twig environment - App::singleton('twig.environment.cms', function ($app) { + App::bind('twig.environment.cms', function ($app) { // Load Twig options $useCache = !Config::get('cms.twigNoCache'); $isDebugMode = Config::get('app.debug', false); diff --git a/modules/cms/classes/AutoDatasource.php b/modules/cms/classes/AutoDatasource.php index 7b3a289c75..3b9aae08e5 100644 --- a/modules/cms/classes/AutoDatasource.php +++ b/modules/cms/classes/AutoDatasource.php @@ -482,7 +482,7 @@ public function delete(string $dirName, string $fileName, string $extension): bo /** * @inheritDoc */ - public function lastModified(string $dirName, string $fileName, string $extension): int + public function lastModified(string $dirName, string $fileName, string $extension): ?int { return $this->getDatasourceForPath($this->makeFilePath($dirName, $fileName, $extension))->lastModified($dirName, $fileName, $extension); } diff --git a/modules/cms/console/CreateTheme.php b/modules/cms/console/CreateTheme.php index 17e30c68d3..586c2f5bfc 100644 --- a/modules/cms/console/CreateTheme.php +++ b/modules/cms/console/CreateTheme.php @@ -67,7 +67,7 @@ class CreateTheme extends GeneratorCommand 'scaffold/theme/tailwind/partials/site/footer.stub' => 'partials/site/footer.htm', 'scaffold/theme/tailwind/.gitignore.stub' => '.gitignore', 'scaffold/theme/tailwind/package.stub' => 'package.json', - 'scaffold/theme/tailwind/readme.stub' => 'README.md', + 'scaffold/theme/tailwind/README.stub' => 'README.md', 'scaffold/theme/tailwind/tailwind.config.stub' => 'tailwind.config.js', 'scaffold/theme/tailwind/theme.stub' => 'theme.yaml', 'scaffold/theme/tailwind/version.stub' => 'version.yaml', diff --git a/modules/cms/lang/de/lang.php b/modules/cms/lang/de/lang.php index 121faf24ba..8ba5afb02c 100644 --- a/modules/cms/lang/de/lang.php +++ b/modules/cms/lang/de/lang.php @@ -3,54 +3,54 @@ return [ 'cms_object' => [ 'invalid_file' => 'Ungültiger Dateiname: :name. Diese dürfen nur alphanumerische Symbole, Unter- und Bindestriche sowie Punkte enthalten. Beispiele: page.htm, page, subdirectory/page', - 'invalid_property' => 'Die Eigenschaft ":name" kann nicht angewendet werden', - 'file_already_exists' => 'Datei ":name" existiert bereits.', - 'error_saving' => 'Fehler beim Speichern von ":name".', - 'error_creating_directory' => 'Fehler beim Erstellen von Verzeichnis mit Namen :name', - 'invalid_file_extension'=>'Ungültige Dateiendung: :invalid. Erlaubt sind: :allowed.', - 'error_deleting' => 'Fehler beim Löschen der Template-Datei ":name".', - 'delete_success' => 'Templates wurden erfolgreich gelöscht: :count.', - 'file_name_required' => 'Ein Dateiname ist erforderlich.', + 'invalid_property' => 'Die Eigenschaft ":name" kann nicht angewendet werden.', + 'file_already_exists' => 'Die Datei ":name" existiert bereits.', + 'error_saving' => 'Fehler beim Speichern von ":name". Bitte Berechtigungen überprüfen.', + 'error_creating_directory' => 'Fehler beim Erstellen von Verzeichnis mit Namen :name. Bitte Berechtigungen überprüfen.', + 'invalid_file_extension' => 'Ungültige Dateiendung: :invalid. Erlaubt sind: :allowed.', + 'error_deleting' => 'Fehler beim Löschen der Template-Datei ":name". Bitte Berechtigungen überprüfen.', + 'delete_success' => 'Templates wurden erfolgreich gelöscht: :count', + 'file_name_required' => 'Die Vergabe des Dateinames ist erforderlich.', 'safe_mode_enabled' => 'Der abgesicherte Modus ist derzeit aktiviert. Die Bearbeitung des PHP-Codes von CMS-Templates ist deaktiviert. Um den abgesicherten Modus zu deaktivieren, setzen Sie den Konfigurationswert `cms.enableSafeMode` auf `false`.', ], 'dashboard' => [ 'active_theme' => [ - 'widget_title_default' => 'Website', + 'widget_title_default' => 'Webseite', 'online' => 'Online', - 'maintenance' => 'In der Wartung', - 'manage_themes' => 'Themes Verwalten', + 'maintenance' => 'In Wartung', + 'manage_themes' => 'Themes verwalten', 'customize_theme' => 'Theme anpassen', ], ], 'theme' => [ - 'not_found_name' => "Das Theme ':name' konnte nicht gefunden werden.", + 'not_found_name' => 'Das Theme ":name" konnte nicht gefunden werden.', 'by_author' => 'Von :name', 'active' => [ - 'not_set' => "Aktives Theme nicht definiert", - 'not_found' => 'Aktives Theme wurde nicht gefunden.', + 'not_set' => 'Es ist kein aktives Theme definiert.', + 'not_found' => 'Das aktive Theme wurde nicht gefunden.', ], 'edit' => [ - 'not_set' => "Edit Theme nicht definiert", - 'not_found' => "Edit Theme nicht gefunden.", - 'not_match' => "Das Objekt, das sie anzupassen versuchen gehört nicht zum Theme in Bearbeitung. Bitte laden Sie die Seite erneut." + 'not_set' => 'Themenverwaltung nicht definiert.', + 'not_found' => 'Themenverwaltung nicht gefunden.', + 'not_match' => 'Das Objekt, das Sie anzupassen versuchen gehört nicht zum zu bearbeitenden Theme. Bitte laden Sie die Seite erneut.' ], 'settings_menu' => 'Frontend Theme', - 'settings_menu_description' => 'Rufe eine Liste installierter Themes auf und wähle ein aktives aus.', + 'settings_menu_description' => 'Verwalten und passen Sie das Frontend-Theme an.', 'default_tab' => 'Eigenschaften', 'name_label' => 'Name', - 'name_create_placeholder' => 'Neuer Themename', + 'name_create_placeholder' => 'Neuer Theme-Name', 'author_label' => 'Autor', 'author_placeholder' => 'Autor- oder Firmenname', 'description_label' => 'Beschreibung', - 'description_placeholder' => 'Themebeschreibung', + 'description_placeholder' => 'Theme-Beschreibung', 'homepage_label' => 'Homepage', - 'homepage_placeholder' => 'Webseiten URL', + 'homepage_placeholder' => 'Webseiten-URL', 'code_label' => 'Code', - 'code_placeholder' => 'Ein einzigartiger Code genutzt bei der Weiterverbreitung dieses Themes', - 'preview_image_label' => 'Bildvorschau', + 'code_placeholder' => 'Ein einzigartiger Code, der bei der Weiterverbreitung dieses Themes genutzt wird', + 'preview_image_label' => 'Vorschau-Bild', 'preview_image_placeholder' => 'Der Pfad des Theme-Vorschaubildes.', 'dir_name_label' => 'Verzeichnisname', - 'dir_name_create_label' => 'Name des Zielverzeichnisses', + 'dir_name_create_label' => 'Name des Theme-Zielverzeichnisses', 'theme_label' => 'Theme', 'theme_title' => 'Themes', 'activate_button' => 'Aktivieren', @@ -70,13 +70,13 @@ 'import_theme_success' => 'Theme erfolgreich importiert!', 'import_uploaded_file' => 'Theme Archivdatei', 'import_overwrite_label' => 'Überschreibe existierende Dateien', - 'import_overwrite_comment' => 'Deaktiviere diese Option, um ausschließlich neue Dateien zu importieren', + 'import_overwrite_comment' => 'Deaktivieren Sie diese Option, um ausschließlich neue Dateien zu importieren', 'import_folders_label' => 'Ordner', - 'import_folders_comment' => 'Bitte wähle die Theme-Ordner zum Importieren aus', + 'import_folders_comment' => 'Bitte wählen Sie die Theme-Ordner zum Importieren aus', 'export_button' => 'Exportieren', - 'export_title' => 'Exportiere Theme', + 'export_title' => 'Theme exportieren', 'export_folders_label' => 'Ordner', - 'export_folders_comment' => 'Bitte wählen Sie die Ordner des Themes, die Sie exportieren wollen, aus.', + 'export_folders_comment' => 'Bitte wählen Sie die Ordner des Themes aus, die Sie exportieren wollen.', 'delete_button' => 'Löschen', 'delete_confirm' => 'Sind Sie sicher, dass Sie dieses Theme löschen wollen? Dies kann nicht rückgängig gemacht werden!', 'delete_active_theme_failed' => 'Das aktive Theme kann nicht gelöscht werden, aktivieren Sie zunächst ein anderes Theme.', @@ -86,30 +86,37 @@ 'create_new_blank_theme' => 'Erstelle ein neues (leeres) Theme', 'create_theme_success' => 'Theme erfolgreich erstellt!', 'create_theme_required_name' => 'Bitte benennen Sie das Theme.', - 'new_directory_name_label' => 'Theme Verzeichnis', + 'new_directory_name_label' => 'Theme-Verzeichnis', 'new_directory_name_comment' => 'Stellen Sie einen neuen Verzeichnisnamen für das duplizierte Theme bereit.', 'dir_name_invalid' => 'Verzeichnisnamen können nur Zahlen, lateinische Buchstaben und die folgenden Symbole enthalten: _-', - 'dir_name_taken' => 'Gewünschter Verzeichnisname existiert bereits.', - 'find_more_themes' => 'Finde weitere Themen', + 'dir_name_taken' => 'Der gewünschte Verzeichnisname existiert bereits.', + 'find_more_themes' => 'Finde weitere Themes', 'saving' => 'Theme speichern...', - 'return' => 'Zur Themeliste zurückkehren', + 'return' => 'Zur Theme-Liste zurückkehren', ], 'maintenance' => [ 'settings_menu' => 'Wartungsmodus', 'settings_menu_description' => 'Konfigurieren Sie den Wartungsmodus.', 'is_enabled' => 'Wartungsmodus aktivieren', 'is_enabled_comment' => 'Sobald aktiviert, werden Besucher die unten ausgewählte Seite sehen.', - 'hint' => 'Im Wartungsmodus wird die Wartungsseite für Besucher angezeigt, die nicht im Back-End-Bereich angemeldet sind.', + 'hint' => 'Im Wartungsmodus wird die Wartungsseite für Besucher angezeigt, die nicht im Backend-Bereich angemeldet sind.', + 'allowed_ips' => [ + 'name' => 'Erlaubte IP-Adressen', + 'description' => 'Die angegebenen IP-Adressen, sehen die Webseite trotz aktiviertem Wartungsmodus.', + 'prompt' => 'IP-Adresse hinzufügen', + 'ip' => 'IP-Adresse', + 'label' => 'Beschreibung', + ], ], 'page' => [ - 'not_found_name' => "Die Seite ':name' konnte nicht gefunden werden", + 'not_found_name' => 'Die Seite ":name" konnte nicht gefunden werden.', 'not_found' => [ - 'label' => "Seite nicht gefunden", - 'help' => "Die angeforderte Seite kann nicht gefunden werden.", + 'label' => 'Seite nicht gefunden', + 'help' => 'Die angeforderte Seite konnte nicht gefunden werden.', ], 'custom_error' => [ - 'label' => "Seitenfehler", - 'help' => "Entschuldigung, ein Fehler trat auf, sodass die gewünschte Seite nicht angezeigt werden kann.", + 'label' => 'Seitenfehler', + 'help' => 'Entschuldigung, ein Fehler ist aufgetreten, sodass die gewünschte Seite nicht angezeigt werden kann.', ], 'menu_label' => 'Seiten', 'unsaved_label' => 'Ungespeicherte Seite(n)', @@ -119,13 +126,13 @@ 'delete_confirm_multiple' => 'Wollen Sie die ausgewählten Seiten wirklich löschen?', 'delete_confirm_single' => 'Wollen Sie diese Seite wirklich löschen?', 'no_layout' => '-- Kein Layout --', - 'cms_page' => 'CMS Seite', + 'cms_page' => 'CMS-Seite', 'title' => 'Seitentitel', 'url' => 'Seiten-URL', 'file_name' => 'Seiten-Dateiname', ], 'layout' => [ - 'not_found_name' => "Das Layout ':name' wurde nicht gefunden", + 'not_found_name' => 'Das Layout ":name" wurde nicht gefunden.', 'menu_label' => 'Layouts', 'unsaved_label' => 'Ungespeicherte(s) Layout(s)', 'no_list_records' => 'Keine Layouts gefunden', @@ -134,8 +141,8 @@ 'delete_confirm_single' => 'Wollen Sie das ausgewählte Layout wirklich löschen?' ], 'partial' => [ - 'not_found_name' => "Das Partial ':name' wurde nicht gefunden.", - 'invalid_name' => "Ungültiger Partial-Name: :name.", + 'not_found_name' => 'Das Partial ":name" wurde nicht gefunden.', + 'invalid_name' => 'Ungültiger Partial-Name: :name.', 'menu_label' => 'Partials', 'unsaved_label' => 'Ungespeicherte(s) Partial(s)', 'no_list_records' => 'Keine Partials gefunden', @@ -144,20 +151,20 @@ 'new' => 'Neues Partial' ], 'content' => [ - 'not_found_name' => "Die Inhaltsdatei ':name' wurde nicht gefunden.", + 'not_found_name' => 'Die Inhaltsdatei ":name" wurde nicht gefunden.', 'menu_label' => 'Inhalt', - 'unsaved_label' => 'Ungespeicherter Inhalt', + 'unsaved_label' => 'Ungespeicherte(r) Inhalt(e)', 'no_list_records' => 'Keine Inhaltsdateien gefunden', 'delete_confirm_multiple' => 'Wollen Sie die ausgewählten Inhalte und Verzeichnisse wirklich löschen?', 'delete_confirm_single' => 'Wollen Sie diese Inhaltsdatei wirklich löschen?', 'new' => 'Neue Inhaltsdatei' ], 'ajax_handler' => [ - 'invalid_name' => "Ungültiger Name für AJAX Handler: :name.", - 'not_found' => "AJAX Handler ':name' wurde nicht gefunden.", + 'invalid_name' => 'Ungültiger Name für AJAX Handler: :name.', + 'not_found' => 'AJAX-Handler ":name" wurde nicht gefunden.', ], 'cms' => [ - 'menu_label' => "CMS" + 'menu_label' => 'CMS' ], 'sidebar' => [ 'add' => 'Hinzufügen', @@ -173,8 +180,8 @@ 'description' => 'Beschreibung', 'preview' => 'Vorschau', 'meta' => 'Meta', - 'meta_title' => 'Meta Titel', - 'meta_description' => 'Meta Beschreibung', + 'meta_title' => 'Meta-Titel', + 'meta_description' => 'Meta-Beschreibung', 'markup' => 'Markup', 'code' => 'Code', 'content' => 'Inhalt', @@ -188,15 +195,15 @@ 'close_replacebox' => 'Ersetzen-Feld schließen', 'commit' => 'Commit', 'reset' => 'Zurücksetzen', - 'commit_confirm' => 'Sind Sie sicher, dass Sie Ihre Änderungen an dieser Datei auf das Dateisystem übertragen wollen? Dies wird die bestehende Datei auf dem Dateisystem überschreiben', + 'commit_confirm' => 'Sind Sie sicher, dass Sie Ihre Änderungen an dieser Datei auf das Dateisystem übertragen wollen? Dies wird die bestehende Datei auf dem Dateisystem überschreiben.', 'reset_confirm' => 'Sind Sie sicher, dass Sie diese Datei auf die Kopie zurücksetzen wollen, die sich auf dem Dateisystem befindet? Dadurch wird sie vollständig durch die Datei ersetzt, die sich auf dem Dateisystem befindet.', 'committing' => 'Committing', 'resetting' => 'Zurücksetzen', - 'commit_success' => 'Der :type wurde auf das Dateisystem übertragen', - 'reset_success' => 'Der :type wurde auf die Dateisystemversion zurückgesetzt', + 'commit_success' => ':type wurde auf das Dateisystem übertragen', + 'reset_success' => ':type wurde auf die Dateisystemversion zurückgesetzt', ], 'asset' => [ - 'menu_label' => "Assets", + 'menu_label' => 'Assets', 'unsaved_label' => 'Ungespeicherte(s) Asset(s)', 'drop_down_add_title' => 'Hinzufügen...', 'drop_down_operation_title' => 'Aktion...', @@ -236,23 +243,24 @@ 'path' => 'Pfad' ], 'component' => [ - 'menu_label' => "Komponenten", - 'unnamed' => "Unbenannt", - 'no_description' => "Keine Beschreibung angegeben", - 'alias' => "Verknüpfung", - 'alias_description' => "Dieser Komponente wird ein eindeutiger Name gegeben, wenn sie im Code von Seite oder Layout benutzt wird.", - 'validation_message' => "Komponentenverknüpfungen werden benötigt und dürfen nur lateinische Zeichen, Ziffern und Unterstriche beinhalten. Die Verknüpfungen müssen mit einem lateinischen Zeichen beginnen.", - 'invalid_request' => "Aufgrund ungültiger Komponentendaten kann das Template nicht gespeichert werden.", + 'menu_label' => 'Komponenten', + 'unnamed' => 'Unbenannt', + 'no_description' => 'Keine Beschreibung angegeben', + 'alias' => 'Verknüpfung', + 'alias_description' => 'Dieser Komponente wird ein eindeutiger Name gegeben, wenn sie im Code von Seite oder Layout benutzt wird.', + 'validation_message' => 'Komponentenverknüpfungen werden benötigt und dürfen nur lateinische Zeichen, Ziffern und Unterstriche beinhalten. Die Verknüpfungen müssen mit einem lateinischen Zeichen beginnen.', + 'invalid_request' => 'Aufgrund ungültiger Komponentendaten kann das Template nicht gespeichert werden.', 'no_records' => 'Keine Komponenten gefunden', - 'not_found' => "Die Komponente ':name' wurde nicht gefunden.", - 'no_default_partial' => "Diese Komponente hat keinen 'default' Partial", - 'method_not_found' => "Die Komponente ':name' enthält keine Methode mit Namen ':method'.", + 'not_found' => 'Die Komponente ":name" wurde nicht gefunden.', + 'no_default_partial' => 'Diese Komponente hat kein "default"-Partial', + 'method_not_found' => 'Die Komponente ":name" enthält keine Methode mit Namen ":method".', + 'soft_component' => 'Soft-Komponente', 'soft_component_description' => 'Diese Komponente fehlt, aber Sie ist optional.', ], 'template' => [ - 'invalid_type' => "Unbekannter Template-Typ.", - 'not_found' => "Das angeforderte Template wurde nicht gefunden.", - 'saved'=> "Das Template wurde erfolgreich gespeichert.", + 'invalid_type' => 'Unbekannter Template-Typ.', + 'not_found' => 'Das angeforderte Template wurde nicht gefunden.', + 'saved' => 'Das Template wurde erfolgreich gespeichert.', 'no_list_records' => 'Keine Einträge gefunden', 'delete_confirm' => 'Ausgewählte Templates löschen?', 'order_by' => 'Sortieren nach', @@ -268,15 +276,15 @@ 'manage_theme_options' => 'Konfigurieren Sie Anpassungsoptionen für das aktive Theme', ], 'theme_log' => [ - 'hint' => 'Dieses Protokoll zeigt alle Änderungen an, die von Administratoren im Back-End-Bereich am Theme vorgenommen wurden.', - 'menu_label' => 'Theme Protokoll', + 'hint' => 'Dieses Protokoll zeigt alle Änderungen an, die von Administratoren im Backend-Bereich am Theme vorgenommen wurden.', + 'menu_label' => 'Theme-Protokoll', 'menu_description' => 'Zeigen Sie die am aktiven Theme vorgenommenen Änderungen an.', - 'empty_link' => 'Leeres Theme Protokoll', - 'empty_loading' => 'Leeren des Theme Protokolls...', - 'empty_success' => 'Theme Protokoll', - 'return_link' => 'Zurück zum Theme Protokoll', + 'empty_link' => 'Leeres Theme-Protokoll', + 'empty_loading' => 'Leeren des Theme-Protokolls...', + 'empty_success' => 'Theme-Protokoll', + 'return_link' => 'Zurück zum Theme-Protokoll', 'id' => 'ID', - 'id_label' => 'Protokoll ID', + 'id_label' => 'Protokoll-ID', 'created_at' => 'Datum & Zeit', 'user' => 'Benutzer', 'type' => 'Typ', diff --git a/modules/cms/phpunit.xml b/modules/cms/phpunit.xml index 4163561102..4cb34b9f38 100644 --- a/modules/cms/phpunit.xml +++ b/modules/cms/phpunit.xml @@ -1,22 +1,17 @@ - ./tests - - - - - diff --git a/modules/cms/twig/SnowboardNode.php b/modules/cms/twig/SnowboardNode.php index 05789876b3..9c1128cf62 100644 --- a/modules/cms/twig/SnowboardNode.php +++ b/modules/cms/twig/SnowboardNode.php @@ -48,8 +48,8 @@ public function compile(TwigCompiler $compiler) 'attr' => 'snowboard.data-attr', 'extras' => 'snowboard.extras', ]; - $manifestPath = Request::getBasePath() . '/modules/system/assets/js/build/manifest.js'; - $basePath = Request::getBasePath() . '/modules/system/assets/js/snowboard/build/'; + $manifestPath = Url::asset('/modules/system/assets/js/build/manifest.js'); + $basePath = Url::asset('/modules/system/assets/js/snowboard/build') . '/'; if (!static::$baseLoaded) { // Add manifest and vendor files diff --git a/modules/system/tests/js/.babelrc b/modules/system/.babelrc similarity index 89% rename from modules/system/tests/js/.babelrc rename to modules/system/.babelrc index 710cfd1b16..d6a9403c25 100644 --- a/modules/system/tests/js/.babelrc +++ b/modules/system/.babelrc @@ -6,7 +6,7 @@ "@babel/plugin-transform-runtime", [ "module-resolver", { - "root": ["."], + "root": ["./tests/js"], "alias": { "helpers": "./helpers", "snowboard": "../../modules/system/assets/js/snowboard", diff --git a/modules/system/.eslintrc.json b/modules/system/.eslintrc.json index 96bf04b4ef..1c1a672e30 100644 --- a/modules/system/.eslintrc.json +++ b/modules/system/.eslintrc.json @@ -18,6 +18,7 @@ "max-len": ["off"], "new-cap": ["error", { "properties": false }], "no-alert": ["off"], + "no-plusplus": "off", "no-param-reassign": ["error", { "props": false }], @@ -32,5 +33,17 @@ "math": "always" }], "vue/multi-word-component-names": ["off"] - } + }, + "ignorePatterns": [ + "assets/js/eventlogs", + "assets/js/framework.js", + "assets/js/framework*.js", + "assets/js/lang", + "assets/js/mailbrandsettings", + "assets/js/updates", + "assets/ui", + "assets/vendor", + "tests/js", + "**/build/*.js" + ] } diff --git a/modules/system/LICENSE b/modules/system/LICENSE new file mode 100644 index 0000000000..7b47a3b139 --- /dev/null +++ b/modules/system/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2013-2021.03.01 October CMS +Copyright (c) 2021 Winter CMS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/modules/system/README.md b/modules/system/README.md new file mode 100644 index 0000000000..875de1a232 --- /dev/null +++ b/modules/system/README.md @@ -0,0 +1,5 @@ +# Winter CMS - System Module + +This repository is a read-only sub-split of the Winter CMS `System` module for use in Composer. Please note that we do not accept any pull requests to this repository. + +If you wish to make changes to this module, please submit them to the [main repository](https://github.com/wintercms/winter). diff --git a/modules/system/ServiceProvider.php b/modules/system/ServiceProvider.php index 5eb7d52dcb..eed836ecaa 100644 --- a/modules/system/ServiceProvider.php +++ b/modules/system/ServiceProvider.php @@ -136,7 +136,7 @@ protected function registerSingletons() protected function registerPrivilegedActions() { $requests = ['/combine/', '@/system/updates', '@/system/install', '@/backend/auth']; - $commands = ['winter:up', 'winter:update', 'winter:env', 'winter:version', 'winter:manifest']; + $commands = ['migrate', 'winter:up', 'winter:update', 'winter:env', 'winter:version', 'winter:manifest']; /* * Requests @@ -274,6 +274,7 @@ protected function registerConsole() $this->registerConsoleCommand('mix.list', \System\Console\MixList::class); $this->registerConsoleCommand('mix.compile', \System\Console\MixCompile::class); $this->registerConsoleCommand('mix.watch', \System\Console\MixWatch::class); + $this->registerConsoleCommand('mix.run', \System\Console\MixRun::class); } /* @@ -446,7 +447,7 @@ protected function registerBackendPermissions() 'label' => 'system::lang.permissions.manage_mail_templates', 'tab' => 'system::lang.permissions.name', 'roles' => [UserRole::CODE_DEVELOPER], - ] + ], ]); $manager->registerPermissionOwnerAlias('Winter.System', 'October.System'); }); diff --git a/modules/system/assets/js/build/manifest.js b/modules/system/assets/js/build/manifest.js index 15c3878c30..6bb0026d28 100644 --- a/modules/system/assets/js/build/manifest.js +++ b/modules/system/assets/js/build/manifest.js @@ -1 +1 @@ -!function(){"use strict";var n,r={},t={};function e(n){var o=t[n];if(void 0!==o)return o.exports;var u=t[n]={exports:{}};return r[n](u,u.exports,e),u.exports}e.m=r,n=[],e.O=function(r,t,o,u){if(!t){var i=1/0;for(a=0;a=u)&&Object.keys(e.O).every((function(n){return e.O[n](t[c])}))?t.splice(c--,1):(f=!1,u0&&n[a-1][2]>u;a--)n[a]=n[a-1];n[a]=[t,o,u]},e.n=function(n){var r=n&&n.__esModule?function(){return n.default}:function(){return n};return e.d(r,{a:r}),r},e.d=function(n,r){for(var t in r)e.o(r,t)&&!e.o(n,t)&&Object.defineProperty(n,t,{enumerable:!0,get:r[t]})},e.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(n){if("object"==typeof window)return window}}(),e.o=function(n,r){return Object.prototype.hasOwnProperty.call(n,r)},function(){var n={911:0};e.O.j=function(r){return 0===n[r]};var r=function(r,t){var o,u,i=t[0],f=t[1],c=t[2],s=0;if(i.some((function(r){return 0!==n[r]}))){for(o in f)e.o(f,o)&&(e.m[o]=f[o]);if(c)var a=c(e)}for(r&&r(t);s=i)&&Object.keys(t.O).every((function(r){return t.O[r](e[c])}))?e.splice(c--,1):(f=!1,i0&&r[a-1][2]>i;a--)r[a]=r[a-1];r[a]=[e,o,i]},t.d=function(r,n){for(var e in n)t.o(n,e)&&!t.o(r,e)&&Object.defineProperty(r,e,{enumerable:!0,get:n[e]})},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},function(){var r={911:0};t.O.j=function(n){return 0===r[n]};var n=function(n,e){var o,i,u=e[0],f=e[1],c=e[2],s=0;if(u.some((function(n){return 0!==r[n]}))){for(o in f)t.o(f,o)&&(t.m[o]=f[o]);if(c)var a=c(t)}for(n&&n(e);s{t&&this.doAjax().then((t=>{if(t.cancelled)return this.cancelled=!0,void this.complete();this.responseData=t,this.processUpdate(t).then((()=>{!1===t.X_WINTER_SUCCESS?this.processError(t):this.processResponse(t)}))}),(t=>{this.responseError=t,this.processError(t)}))})):this.doAjax().then((t=>{if(t.cancelled)return this.cancelled=!0,void this.complete();this.responseData=t,this.processUpdate(t).then((()=>{!1===t.X_WINTER_SUCCESS?this.processError(t):this.processResponse(t)}))}),(t=>{this.responseError=t,this.processError(t)})):this.cancelled=!0}else this.cancelled=!0}dependencies(){return["cookie","jsonParser"]}checkRequest(){if(this.element&&this.element instanceof Element==!1)throw new Error("The element provided must be an Element instance");if(void 0===this.handler)throw new Error("The AJAX handler name is not specified.");if(!this.handler.match(/^(?:\w+:{2})?on*/))throw new Error('Invalid AJAX handler name. The correct handler name format is: "onEvent".')}getFetch(){return this.fetchOptions=void 0!==this.options.fetchOptions&&"object"==typeof this.options.fetchOptions?this.options.fetchOptions:{method:"POST",headers:this.headers,body:this.data,redirect:"follow",mode:"same-origin"},this.snowboard.globalEvent("ajaxFetchOptions",this.fetchOptions,this),fetch(this.url,this.fetchOptions)}doClientValidation(){return!0!==this.options.browserValidate||!this.form||!1!==this.form.checkValidity()||(this.form.reportValidity(),!1)}doAjax(){if(!1===this.snowboard.globalEvent("ajaxBeforeSend",this))return Promise.resolve({cancelled:!0});const t=new Promise(((t,e)=>{this.getFetch().then((n=>{n.ok||406===n.status?n.headers.has("Content-Type")&&n.headers.get("Content-Type").includes("/json")?n.json().then((e=>{t(o(o({},e),{},{X_WINTER_SUCCESS:406!==n.status,X_WINTER_RESPONSE_CODE:n.status}))}),(t=>{e(this.renderError("Unable to parse JSON response: ".concat(t)))})):n.text().then((e=>{t(e)}),(t=>{e(this.renderError("Unable to process response: ".concat(t)))})):n.headers.has("Content-Type")&&n.headers.get("Content-Type").includes("/json")?n.json().then((t=>{e(this.renderError(t.message,t.exception,t.file,t.line,t.trace))}),(t=>{e(this.renderError("Unable to parse JSON response: ".concat(t)))})):n.text().then((t=>{e(this.renderError(t))}),(t=>{e(this.renderError("Unable to process response: ".concat(t)))}))}),(t=>{e(this.renderError("Unable to retrieve a response from the server: ".concat(t)))}))}));if(this.snowboard.globalEvent("ajaxStart",t,this),this.element){const e=new Event("ajaxPromise");e.promise=t,this.element.dispatchEvent(e)}return t}processUpdate(t){return new Promise(((e,n)=>{if("function"==typeof this.options.beforeUpdate&&!1===this.options.beforeUpdate.apply(this,[t]))return void n();const r={};if(Object.entries(t).forEach((t=>{const[e,n]=t;"X_WINTER"!==e.substr(0,8)&&(r[e]=n)})),0===Object.keys(r).length)return void(t.X_WINTER_ASSETS?this.processAssets(t.X_WINTER_ASSETS).then((()=>{e()}),(()=>{n()})):e());this.snowboard.globalPromiseEvent("ajaxBeforeUpdate",t,this).then((async()=>{t.X_WINTER_ASSETS&&await this.processAssets(t.X_WINTER_ASSETS),this.doUpdate(r).then((()=>{window.requestAnimationFrame((()=>e()))}),(()=>{n()}))}),(()=>{n()}))}))}doUpdate(t){return new Promise((e=>{const n=[];Object.entries(t).forEach((t=>{const[e,r]=t;let o=this.options.update&&this.options.update[e]?this.options.update[e]:e,i="replace";"@"===o.substr(0,1)?(i="append",o=o.substr(1)):"^"===o.substr(0,1)&&(i="prepend",o=o.substr(1));const s=document.querySelectorAll(o);s.length>0&&s.forEach((t=>{switch(i){case"append":t.innerHTML+=r;break;case"prepend":t.innerHTML=r+t.innerHTML;break;default:t.innerHTML=r}n.push(t),this.snowboard.globalEvent("ajaxUpdate",t,r,this);const e=new Event("ajaxUpdate");e.content=r,t.dispatchEvent(e)}))})),this.snowboard.globalEvent("ajaxUpdateComplete",n,this),e()}))}processResponse(t){if((!this.options.success||"function"!=typeof this.options.success||!1!==this.options.success(this.responseData,this))&&!1!==this.snowboard.globalEvent("ajaxSuccess",this.responseData,this)){if(this.element){const t=new Event("ajaxDone",{cancelable:!0});if(t.responseData=this.responseData,t.request=this,this.element.dispatchEvent(t),t.defaultPrevented)return}this.flash&&t.X_WINTER_FLASH_MESSAGES&&this.processFlashMessages(t.X_WINTER_FLASH_MESSAGES),this.redirect||t.X_WINTER_REDIRECT?this.processRedirect(this.redirect||t.X_WINTER_REDIRECT):this.complete()}}processError(t){if((!this.options.error||"function"!=typeof this.options.error||!1!==this.options.error(this.responseError,this))&&!1!==this.snowboard.globalEvent("ajaxError",this.responseError,this)){if(this.element){const t=new Event("ajaxFail",{cancelable:!0});if(t.responseError=this.responseError,t.request=this,this.element.dispatchEvent(t),t.defaultPrevented)return}t instanceof Error?this.processErrorMessage(t.message):(t.X_WINTER_ERROR_FIELDS&&this.processValidationErrors(t.X_WINTER_ERROR_FIELDS),t.X_WINTER_ERROR_MESSAGE&&this.processErrorMessage(t.X_WINTER_ERROR_MESSAGE)),this.complete()}}processRedirect(t){"function"==typeof this.options.handleRedirectResponse&&!1===this.options.handleRedirectResponse.apply(this,[t])||!1!==this.snowboard.globalEvent("ajaxRedirect",t,this)&&(window.addEventListener("popstate",(()=>{if(this.element){const t=document.createEvent("CustomEvent");t.eventName="ajaxRedirected",this.element.dispatchEvent(t)}}),{once:!0}),window.location.assign(t))}processErrorMessage(t){"function"==typeof this.options.handleErrorMessage&&!1===this.options.handleErrorMessage.apply(this,[t])||!1!==this.snowboard.globalEvent("ajaxErrorMessage",t,this)&&window.alert(t)}processFlashMessages(t){"function"==typeof this.options.handleFlashMessages&&!1===this.options.handleFlashMessages.apply(this,[t])||this.snowboard.globalEvent("ajaxFlashMessages",t,this)}processValidationErrors(t){"function"==typeof this.options.handleValidationErrors&&!1===this.options.handleValidationErrors.apply(this,[this.form,t])||this.snowboard.globalEvent("ajaxValidationErrors",this.form,t,this)}processAssets(t){return this.snowboard.globalPromiseEvent("ajaxLoadAssets",t)}async doConfirm(){if("function"==typeof this.options.handleConfirmMessage)return!1!==this.options.handleConfirmMessage.apply(this,[this.confirm]);if(0===this.snowboard.listensToEvent("ajaxConfirmMessage").length)return window.confirm(this.confirm);const t=this.snowboard.globalPromiseEvent("ajaxConfirmMessage",this.confirm,this);try{if(await t)return!0}catch(t){return!1}return!1}complete(){if(this.options.complete&&"function"==typeof this.options.complete&&this.options.complete(this.responseData,this),this.snowboard.globalEvent("ajaxDone",this.responseData,this),this.element){const t=new Event("ajaxAlways");t.request=this,t.responseData=this.responseData,t.responseError=this.responseError,this.element.dispatchEvent(t)}this.destruct()}get form(){return this.options.form?"string"==typeof this.options.form?document.querySelector(this.options.form):this.options.form:this.element?"FORM"===this.element.tagName?this.element:this.element.closest("form"):null}get context(){return{handler:this.handler,options:this.options}}get headers(){const t={"X-Requested-With":"XMLHttpRequest","X-WINTER-REQUEST-HANDLER":this.handler,"X-WINTER-REQUEST-PARTIALS":this.extractPartials(this.options.update||[])};return this.flash&&(t["X-WINTER-REQUEST-FLASH"]=1),this.xsrfToken&&(t["X-XSRF-TOKEN"]=this.xsrfToken),t}get loading(){return this.options.loading||!1}get url(){return this.options.url||window.location.href}get redirect(){return this.options.redirect&&this.options.redirect.length?this.options.redirect:null}get flash(){return this.options.flash||!1}get files(){return!0===this.options.files&&(void 0!==FormData||(this.snowboard.debug("This browser does not support file uploads"),!1))}get xsrfToken(){return this.snowboard.cookie().get("XSRF-TOKEN")}get data(){const t="object"==typeof this.options.data?this.options.data:{},e=new FormData(this.form||void 0);return Object.keys(t).length>0&&Object.entries(t).forEach((t=>{const[n,r]=t;e.append(n,r)})),e}get confirm(){return this.options.confirm||!1}extractPartials(t){return Object.keys(t).join("&")}renderError(t,e,n,r,o){const i=new Error(t);return i.exception=e||null,i.file=n||null,i.line=r||null,i.trace=o||[],i}}Snowboard.addPlugin("request",s)},8809:function(t,e,n){"use strict";n.d(e,{Z:function(){return r}});n(6886);class r extends window.Snowboard.Singleton{listens(){return{ajaxLoadAssets:"load"}}async load(t){if(t.js&&t.js.length>0)for(const e of t.js)try{await this.loadScript(e)}catch(t){return Promise.reject(t)}if(t.css&&t.css.length>0)for(const e of t.css)try{await this.loadStyle(e)}catch(t){return Promise.reject(t)}if(t.img&&t.img.length>0)for(const e of t.img)try{await this.loadImage(e)}catch(t){return Promise.reject(t)}return Promise.resolve()}loadScript(t){return new Promise(((e,n)=>{if(document.querySelector('script[src="'.concat(t,'"]')))return void e();const r=document.createElement("script");r.setAttribute("type","text/javascript"),r.setAttribute("src",t),r.addEventListener("load",(()=>{this.snowboard.globalEvent("assetLoader.loaded","script",t,r),e()})),r.addEventListener("error",(()=>{this.snowboard.globalEvent("assetLoader.error","script",t,r),n(new Error('Unable to load script file: "'.concat(t,'"')))})),document.body.append(r)}))}loadStyle(t){return new Promise(((e,n)=>{if(document.querySelector('link[rel="stylesheet"][href="'.concat(t,'"]')))return void e();const r=document.createElement("link");r.setAttribute("rel","stylesheet"),r.setAttribute("href",t),r.addEventListener("load",(()=>{this.snowboard.globalEvent("assetLoader.loaded","style",t,r),e()})),r.addEventListener("error",(()=>{this.snowboard.globalEvent("assetLoader.error","style",t,r),n(new Error('Unable to load stylesheet file: "'.concat(t,'"')))})),document.head.append(r)}))}loadImage(t){return new Promise(((e,n)=>{const r=new Image;r.addEventListener("load",(()=>{this.snowboard.globalEvent("assetLoader.loaded","image",t,r),e()})),r.addEventListener("error",(()=>{this.snowboard.globalEvent("assetLoader.error","image",t,r),n(new Error('Unable to load image file: "'.concat(t,'"')))})),r.src=t}))}}},9553:function(t,e,n){"use strict";n.d(e,{Z:function(){return r}});class r extends Snowboard.Singleton{dependencies(){return["request"]}listens(){return{ajaxStart:"ajaxStart",ajaxDone:"ajaxDone"}}ajaxStart(t,e){if(e.element)if("FORM"===e.element.tagName){const t=e.element.querySelectorAll("[data-attach-loading]");t.length>0&&t.forEach((t=>{t.classList.add(this.getLoadingClass(t))}))}else void 0!==e.element.dataset.attachLoading&&e.element.classList.add(this.getLoadingClass(e.element))}ajaxDone(t,e){if(e.element)if("FORM"===e.element.tagName){const t=e.element.querySelectorAll("[data-attach-loading]");t.length>0&&t.forEach((t=>{t.classList.remove(this.getLoadingClass(t))}))}else void 0!==e.element.dataset.attachLoading&&e.element.classList.remove(this.getLoadingClass(e.element))}getLoadingClass(t){return void 0!==t.dataset.attachLoading&&""!==t.dataset.attachLoading?t.dataset.attachLoading:"wn-loading"}}},5763:function(t,e,n){"use strict";n.d(e,{Z:function(){return r}});n(9529),n(5940);class r extends Snowboard.PluginBase{construct(t,e){if(t instanceof Snowboard.PluginBase==!1)throw new Error("You must provide a Snowboard plugin to enable data configuration");if(e instanceof HTMLElement==!1)throw new Error("Data configuration can only be extracted from HTML elements");this.instance=t,this.element=e,this.refresh()}get(t){return void 0===t?this.instanceConfig:void 0!==this.instanceConfig[t]?this.instanceConfig[t]:void 0}set(t,e,n){if(void 0===t)throw new Error("You must provide a configuration key to set");this.instanceConfig[t]=e,!0===n&&(this.element.dataset[t]=e)}refresh(){this.acceptedConfigs=this.getAcceptedConfigs(),this.instanceConfig=this.processConfig()}getAcceptedConfigs(){return void 0!==this.instance.acceptAllDataConfigs&&!0===this.instance.acceptAllDataConfigs||void 0!==this.instance.defaults&&"function"==typeof this.instance.defaults&&"object"==typeof this.instance.defaults()&&Object.keys(this.instance.defaults())}getDefaults(){return void 0!==this.instance.defaults&&"function"==typeof this.instance.defaults&&"object"==typeof this.instance.defaults()?this.instance.defaults():{}}processConfig(){const t=this.getDefaults();if(!1===this.acceptedConfigs)return t;for(const e in this.element.dataset)(!0===this.acceptedConfigs||this.acceptedConfigs.includes(e))&&(t[e]=this.coerceValue(this.element.dataset[e]));return t}coerceValue(t){const e=String(t);if("null"===e)return null;if("undefined"!==e){if(e.startsWith("base64:")){const t=e.replace(/^base64:/,""),n=atob(t);return this.coerceValue(n)}if(["true","yes"].includes(e.toLowerCase()))return!0;if(["false","no"].includes(e.toLowerCase()))return!1;if(/^[-+]?[0-9]+(\.[0-9]+)?$/.test(e))return Number(e);try{return this.snowboard.jsonParser().parse(e)}catch(t){return""===e||e}}}}},2270:function(t,e,n){"use strict";n.d(e,{Z:function(){return r}});class r extends Snowboard.PluginBase{construct(t,e,n){if(this.message=t,this.type=e||"default",this.duration=Number(n||7),this.duration<0)throw new Error("Flash duration must be a positive number, or zero");this.clear(),this.timer=null,this.flashTimer=null,this.create()}dependencies(){return["transition"]}destruct(){null!==this.timer&&window.clearTimeout(this.timer),this.flashTimer&&this.flashTimer.remove(),this.flash&&(this.flash.remove(),this.flash=null,this.flashTimer=null),super.destruct()}create(){this.snowboard.globalEvent("flash.create",this),this.flash=document.createElement("DIV"),this.flash.innerHTML=this.message,this.flash.classList.add("flash-message",this.type),this.flash.removeAttribute("data-control"),this.flash.addEventListener("click",(()=>this.remove())),this.flash.addEventListener("mouseover",(()=>this.stopTimer())),this.flash.addEventListener("mouseout",(()=>this.startTimer())),this.duration>0?(this.flashTimer=document.createElement("DIV"),this.flashTimer.classList.add("flash-timer"),this.flash.appendChild(this.flashTimer)):this.flash.classList.add("no-timer"),document.body.appendChild(this.flash),this.snowboard.transition(this.flash,"show",(()=>{this.startTimer()}))}remove(){this.snowboard.globalEvent("flash.remove",this),this.stopTimer(),this.snowboard.transition(this.flash,"hide",(()=>{this.flash.remove(),this.flash=null,this.destruct()}))}clear(){document.querySelectorAll("body > div.flash-message").forEach((t=>t.remove()))}startTimer(){0!==this.duration&&(this.timerTrans=this.snowboard.transition(this.flashTimer,"timeout",null,"".concat(this.duration,".0s"),!0),this.timer=window.setTimeout((()=>this.remove()),1e3*this.duration))}stopTimer(){this.timerTrans&&this.timerTrans.cancel(),this.timer&&window.clearTimeout(this.timer)}}},6277:function(t,e,n){"use strict";n.d(e,{Z:function(){return r}});n(1515);class r extends Snowboard.Singleton{dependencies(){return["request"]}listens(){return{ready:"ready",ajaxStart:"ajaxStart"}}ready(){this.counter=0,this.createStripe()}ajaxStart(t){this.show(),t.catch((()=>{this.hide()})).finally((()=>{this.hide()}))}createStripe(){this.indicator=document.createElement("DIV"),this.stripe=document.createElement("DIV"),this.stripeLoaded=document.createElement("DIV"),this.indicator.classList.add("stripe-loading-indicator","loaded"),this.stripe.classList.add("stripe"),this.stripeLoaded.classList.add("stripe-loaded"),this.indicator.appendChild(this.stripe),this.indicator.appendChild(this.stripeLoaded),document.body.appendChild(this.indicator)}show(){this.counter+=1;const t=this.stripe.cloneNode(!0);this.indicator.appendChild(t),this.stripe.remove(),this.stripe=t,this.counter>1||(this.indicator.classList.remove("loaded"),document.body.classList.add("wn-loading"))}hide(t){this.counter-=1,!0===t&&(this.counter=0),this.counter<=0&&(this.indicator.classList.add("loaded"),document.body.classList.remove("wn-loading"))}}},8032:function(t,e,n){"use strict";n.d(e,{Z:function(){return r}});class r extends Snowboard.Singleton{listens(){return{ready:"ready"}}ready(){let t=!1;if(document.querySelectorAll('link[rel="stylesheet"]').forEach((e=>{e.href.endsWith("/modules/system/assets/css/snowboard.extras.css")&&(t=!0)})),!t){const t=document.createElement("link");t.setAttribute("rel","stylesheet"),t.setAttribute("href",this.snowboard.url().to("/modules/system/assets/css/snowboard.extras.css")),document.head.appendChild(t)}}}},8269:function(t,e,n){"use strict";n.d(e,{Z:function(){return r}});n(6886);class r extends Snowboard.PluginBase{construct(t,e,n,r,o){if(t instanceof HTMLElement==!1)throw new Error("A HTMLElement must be provided for transitioning");if(this.element=t,"string"!=typeof e)throw new Error("Transition name must be specified as a string");if(this.transition=e,n&&"function"!=typeof n)throw new Error("Callback must be a valid function");this.callback=n,this.duration=r?this.parseDuration(r):null,this.trailTo=!0===o,this.doTransition()}eventClasses(){for(var t=arguments.length,e=new Array(t),n=0;n{const[n,r]=t;-1!==e.indexOf(n)&&o.push(r)})),o}doTransition(){null!==this.duration&&(this.element.style.transitionDuration=this.duration),this.resetClasses(),this.eventClasses("in","active").forEach((t=>{this.element.classList.add(t)})),window.requestAnimationFrame((()=>{"0s"!==window.getComputedStyle(this.element)["transition-duration"]?(this.element.addEventListener("transitionend",(()=>this.onTransitionEnd()),{once:!0}),window.requestAnimationFrame((()=>{this.element.classList.remove(this.eventClasses("in")[0]),this.element.classList.add(this.eventClasses("out")[0])}))):(this.resetClasses(),this.callback&&this.callback.apply(this.element),this.destruct())}))}onTransitionEnd(){this.eventClasses("active",this.trailTo?"":"out").forEach((t=>{this.element.classList.remove(t)})),this.callback&&this.callback.apply(this.element),null!==this.duration&&(this.element.style.transitionDuration=null),this.destruct()}cancel(){this.element.removeEventListener("transitionend",(()=>this.onTransitionEnd),{once:!0}),this.resetClasses(),null!==this.duration&&(this.element.style.transitionDuration=null),this.destruct()}resetClasses(){this.eventClasses().forEach((t=>{this.element.classList.remove(t)}))}parseDuration(t){const e=/^([0-9]+(\.[0-9]+)?)(m?s)?$/.exec(t),n=Number(e[1]),r="s"===e[3]?"sec":"msec";return"".concat("sec"===r?1e3*n:Math.floor(n),"ms")}}},1705:function(t,e,n){"use strict";n.d(e,{Z:function(){return p}});n(6886),n(9529);class r{constructor(t){this.snowboard=t}construct(){}dependencies(){return[]}listens(){return{}}destruct(){this.detach(),delete this.snowboard}destructor(){this.destruct()}}class o extends r{}class i{constructor(t,e,n){this.name=t,this.snowboard=e,this.instance=n,this.instances=[],this.singleton=n.prototype instanceof o,this.initialised=n.prototype instanceof r,this.mocks={},this.originalFunctions={}}hasMethod(t){return!this.isFunction()&&"function"==typeof this.instance.prototype[t]}callMethod(){if(this.isFunction())return null;for(var t=arguments.length,e=new Array(t),n=0;n!this.snowboard.getPluginNames().includes(t)));throw new Error('The "'.concat(this.name,'" plugin requires the following plugins: ').concat(t.join(", ")))}if(this.isSingleton())return 0===this.instances.length&&this.initialiseSingleton(...n),Object.keys(this.mocks).length>0&&(Object.entries(this.originalFunctions).forEach((t=>{const[e,n]=t;this.instances[0][e]=n})),Object.entries(this.mocks).forEach((e=>{const[n,r]=e;this.instances[0][n]=function(){for(var e=arguments.length,n=new Array(e),o=0;o0&&(Object.entries(this.originalFunctions).forEach((t=>{const[e,n]=t;this.instance.prototype[e]=n})),Object.entries(this.mocks).forEach((e=>{const[n,r]=e;this.instance.prototype[n]=function(){for(var e=arguments.length,n=new Array(e),o=0;othis.instances.splice(this.instances.indexOf(o),1),o.construct(...n),this.instances.push(o),o}getInstances(){return this.isFunction()?[]:this.instances}isFunction(){return"function"==typeof this.instance&&this.instance.prototype instanceof r==!1}isSingleton(){return this.instance.prototype instanceof o==!0}isInitialised(){return this.initialised}initialiseSingleton(){if(!this.isSingleton())return;for(var t=arguments.length,e=new Array(t),n=0;nthis.instances.splice(this.instances.indexOf(r),1),r.construct(...e),this.instances.push(r),this.initialised=!0}getDependencies(){return this.isFunction()||"function"!=typeof this.instance.prototype.dependencies?[]:this.instance.prototype.dependencies().map((t=>t.toLowerCase()))}dependenciesFulfilled(){const t=this.getDependencies();let e=!0;return t.forEach((t=>{this.snowboard.hasPlugin(t)||(e=!1)})),e}mock(t,e){var n=this;if(!this.isFunction()){if(!this.instance.prototype[t])throw new Error('Function "'.concat(t,'" does not exist and cannot be mocked'));this.mocks[t]=e,this.originalFunctions[t]=this.instance.prototype[t],this.isSingleton()&&0===this.instances.length&&(this.initialiseSingleton(),this.instances[0][t]=function(){for(var t=arguments.length,r=new Array(t),o=0;o{const[e,n]=t;void 0!==this.defaults[e]&&(this.defaults[e]=n)}))}getDefaults(){const t={};return Object.entries(this.defaults).forEach((e=>{const[n,r]=e;null!==this.defaults[n]&&(t[n]=r)})),t}get(t){if(void 0===t){const t=s.Z.get();return Object.entries(t).forEach((e=>{const[n,r]=e;this.snowboard.globalEvent("cookie.get",n,r,(e=>{t[n]=e}))})),t}let e=s.Z.get(t);return this.snowboard.globalEvent("cookie.get",t,e,(t=>{e=t})),e}set(t,e,n){let r=e;return this.snowboard.globalEvent("cookie.set",t,e,(t=>{r=t})),s.Z.set(t,r,c(c({},this.getDefaults()),n))}remove(t,e){s.Z.remove(t,c(c({},this.getDefaults()),e))}}class h extends o{construct(){window.wnJSON=t=>this.parse(t),window.ocJSON=window.wnJSON}parse(t){const e=this.parseString(t);return JSON.parse(e)}parseString(t){let e=t.trim();if(!e.length)throw new Error("Broken JSON object.");let n="",r=null,o=null,i="";for(;e&&","===e[0];)e=e.substr(1);if('"'===e[0]||"'"===e[0]){if(e[e.length-1]!==e[0])throw new Error("Invalid string JSON object.");i='"';for(let t=1;t="0"&&t[e]<="9"){n="";for(let r=e;r="0"&&t[r]<="9"))return{originLength:n.length,body:n};n+=t[r]}throw new Error("Broken JSON number body near ".concat(n))}if("{"===t[e]||"["===t[e]){const r=[t[e]];n=t[e];for(let o=e+1;o=0?e-5:0,50)))}parseKey(t,e,n){let r="";for(let o=e;o="a"&&t[0]<="z"||t[0]>="A"&&t[0]<="Z"||"_"===t[0]||(t[0]>="0"&&t[0]<="9"||("$"===t[0]||t.charCodeAt(0)>255)))}isBlankChar(t){return" "===t||"\n"===t||"\t"===t}}class f extends o{construct(){window.wnSanitize=t=>this.sanitize(t),window.ocSanitize=window.wnSanitize}sanitize(t,e){const n=(new DOMParser).parseFromString(t,"text/html"),r=void 0===e||"boolean"!=typeof e||e;return this.sanitizeNode(n.getRootNode()),r?n.body.innerHTML:n.innerHTML}sanitizeNode(t){if("SCRIPT"===t.tagName)return void t.remove();this.trimAttributes(t);Array.from(t.children).forEach((t=>{this.sanitizeNode(t)}))}trimAttributes(t){if(t.attributes)for(let e=0;e{this.autoInitSingletons&&this.initialiseSingletons(),this.globalEvent("ready"),this.domReady=!0}))}initialiseSingletons(){Object.values(this.plugins).forEach((t=>{t.isSingleton()&&t.dependenciesFulfilled()&&t.initialiseSingleton()}))}addPlugin(t,e){var n=this;const o=t.toLowerCase();if(this.hasPlugin(o))throw new Error('A plugin called "'.concat(t,'" is already registered.'));if("function"!=typeof e&&e instanceof r==!1)throw new Error("The provided plugin must extend the PluginBase class, or must be a callback function.");if(void 0!==this[t]||void 0!==this[o])throw new Error("The given name is already in use for a property or method of the Snowboard class.");this.plugins[o]=new i(o,this,e);const s=function(){return n.plugins[o].getInstance(...arguments)};this[t]=s,this[o]=s,this.debug('Plugin "'.concat(t,'" registered')),Object.values(this.getPlugins()).forEach((t=>{if(t.isSingleton()&&!t.isInitialised()&&t.dependenciesFulfilled()&&t.hasMethod("listens")&&Object.keys(t.callMethod("listens")).includes("ready")&&this.domReady){const e=t.callMethod("listens").ready;t.callMethod(e)}}))}removePlugin(t){const e=t.toLowerCase();this.hasPlugin(e)?(this.plugins[e].getInstances().forEach((t=>{t.destruct()})),delete this.plugins[e],delete this[e],delete this[t],this.debug('Plugin "'.concat(t,'" removed'))):this.debug('Plugin "'.concat(t,'" already removed'))}hasPlugin(t){const e=t.toLowerCase();return void 0!==this.plugins[e]}getPlugins(){return this.plugins}getPluginNames(){return Object.keys(this.plugins)}getPlugin(t){if(!this.hasPlugin(t))throw new Error('No plugin called "'.concat(t,'" has been registered.'));return this.plugins[t]}listensToEvent(t){const e=[];return Object.entries(this.plugins).forEach((n=>{const[r,o]=n;if(o.isFunction())return;if(!o.dependenciesFulfilled())return;if(!o.hasMethod("listens"))return;"string"==typeof o.callMethod("listens")[t]&&e.push(r)})),e}ready(t){this.domReady&&t(),this.on("ready",t)}on(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].includes(e)||this.listeners[t].push(e)}off(t,e){if(!this.listeners[t])return;const n=this.listeners[t].indexOf(e);-1!==n&&this.listeners[t].splice(n,1)}globalEvent(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r{const r=this.getPlugin(e);if(r.isFunction())return;r.isSingleton()&&0===r.getInstances().length&&r.initialiseSingleton();const o=r.callMethod("listens")[t];r.getInstances().forEach((r=>{if(!i){if(!r[o])throw new Error('Missing "'.concat(o,'" method in "').concat(e,'" plugin'));try{!1===r[o](...n)&&(i=!0,this.debug('Global event "'.concat(t,'" cancelled by "').concat(e,'" plugin')))}catch(n){this.error('Error thrown in "'.concat(t,'" event by "').concat(e,'" plugin.'),n)}}}))})),!i&&this.listeners[t]&&this.listeners[t].length>0&&(this.debug("Found ".concat(this.listeners[t].length,' ad-hoc listener(s) for global event "').concat(t,'"')),this.listeners[t].forEach((e=>{if(!i)try{!1===e(...n)&&(i=!0,this.debug('Global event "'.concat(t," cancelled by an ad-hoc listener.")))}catch(e){this.error('Error thrown in "'.concat(t,'" event by an ad-hoc listener.'),e)}}))),!i}globalPromiseEvent(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r{const r=this.getPlugin(e);if(r.isFunction())return;r.isSingleton()&&0===r.getInstances().length&&r.initialiseSingleton();const o=r.callMethod("listens")[t];r.getInstances().forEach((r=>{if(!r[o])throw new Error('Missing "'.concat(o,'" method in "').concat(e,'" plugin'));try{const t=r[o](...n);if(t instanceof Promise==!1)return;i.push(t)}catch(n){this.error('Error thrown in "'.concat(t,'" promise event by "').concat(e,'" plugin.'),n)}}))})),this.listeners[t]&&this.listeners[t].length>0&&(this.debug("Found ".concat(this.listeners[t].length,' ad-hoc listener(s) for global promise event "').concat(t,'"')),this.listeners[t].forEach((e=>{try{const t=e(...n);if(t instanceof Promise==!1)return;i.push(t)}catch(e){this.error('Error thrown in "'.concat(t,'" promise event by an ad-hoc listener.'),e)}}))),0===i.length?Promise.resolve():Promise.all(i)}logMessage(t,e,n){console.groupCollapsed("%c[Snowboard]","color: ".concat(t,"; font-weight: ").concat(e?"bold":"normal",";"),n);for(var r=arguments.length,o=new Array(r>3?r-3:0),i=3;i{t+=1,console.log("%c".concat(t,":"),"color: rgb(88, 88, 88); font-weight: normal;",e)})),console.groupEnd(),console.groupCollapsed("%cTrace","color: rgb(45, 167, 199); font-weight: bold;"),console.trace(),console.groupEnd()}else console.trace();console.groupEnd()}log(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r1?e-1:0),r=1;r1?e-1:0),r=1;r{t.addPlugin("assetLoader",c.Z),t.addPlugin("dataConfig",l.Z),t.addPlugin("extrasStyles",a.Z),t.addPlugin("transition",o.Z),t.addPlugin("flash",r.Z),t.addPlugin("attachLoading",i.Z),t.addPlugin("stripeLoader",s.Z)})(window.Snowboard)},2165:function(t,e,n){"use strict";var r=n(1705);(t=>{const e=new r.Z(!0,!0);t.snowboard=e,t.Snowboard=e,t.SnowBoard=e})(window)},7111:function(t,e,n){var r=n(6733),o=n(9821),i=TypeError;t.exports=function(t){if(r(t))return t;throw i(o(t)+" is not a function")}},7988:function(t,e,n){var r=n(2359),o=n(9821),i=TypeError;t.exports=function(t){if(r(t))return t;throw i(o(t)+" is not a constructor")}},8505:function(t,e,n){var r=n(6733),o=String,i=TypeError;t.exports=function(t){if("object"==typeof t||r(t))return t;throw i("Can't set "+o(t)+" as a prototype")}},9736:function(t,e,n){var r=n(95),o=n(2391),i=n(1787).f,s=r("unscopables"),a=Array.prototype;null==a[s]&&i(a,s,{configurable:!0,value:o(null)}),t.exports=function(t){a[s][t]=!0}},6637:function(t,e,n){"use strict";var r=n(966).charAt;t.exports=function(t,e,n){return e+(n?r(t,e).length:1)}},1176:function(t,e,n){var r=n(5052),o=String,i=TypeError;t.exports=function(t){if(r(t))return t;throw i(o(t)+" is not an object")}},9540:function(t,e,n){var r=n(905),o=n(3231),i=n(9646),s=function(t){return function(e,n,s){var a,c=r(e),l=i(c),u=o(s,l);if(t&&n!=n){for(;l>u;)if((a=c[u++])!=a)return!0}else for(;l>u;u++)if((t||u in c)&&c[u]===n)return t||u||0;return!t&&-1}};t.exports={includes:s(!0),indexOf:s(!1)}},7079:function(t,e,n){var r=n(5968),o=r({}.toString),i=r("".slice);t.exports=function(t){return i(o(t),8,-1)}},1589:function(t,e,n){var r=n(1601),o=n(6733),i=n(7079),s=n(95)("toStringTag"),a=Object,c="Arguments"==i(function(){return arguments}());t.exports=r?i:function(t){var e,n,r;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=function(t,e){try{return t[e]}catch(t){}}(e=a(t),s))?n:c?i(e):"Object"==(r=i(e))&&o(e.callee)?"Arguments":r}},7081:function(t,e,n){var r=n(8270),o=n(4826),i=n(7933),s=n(1787);t.exports=function(t,e,n){for(var a=o(e),c=s.f,l=i.f,u=0;u0&&r[0]<4?1:+(r[0]+r[1])),!o&&s&&(!(r=s.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=s.match(/Chrome\/(\d+)/))&&(o=+r[1]),t.exports=o},3837:function(t){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},3103:function(t,e,n){var r=n(9859),o=n(7933).f,i=n(5762),s=n(4768),a=n(8400),c=n(7081),l=n(6541);t.exports=function(t,e){var n,u,h,f,d,p=t.target,g=t.global,v=t.stat;if(n=g?r:v?r[p]||a(p,{}):(r[p]||{}).prototype)for(u in e){if(f=e[u],h=t.dontCallGetSet?(d=o(n,u))&&d.value:n[u],!l(g?u:p+(v?".":"#")+u,t.forced)&&void 0!==h){if(typeof f==typeof h)continue;c(f,h)}(t.sham||h&&h.sham)&&i(f,"sham",!0),s(n,u,f,t)}}},4229:function(t){t.exports=function(t){try{return!!t()}catch(t){return!0}}},4954:function(t,e,n){"use strict";n(7950);var r=n(5968),o=n(4768),i=n(3466),s=n(4229),a=n(95),c=n(5762),l=a("species"),u=RegExp.prototype;t.exports=function(t,e,n,h){var f=a(t),d=!s((function(){var e={};return e[f]=function(){return 7},7!=""[t](e)})),p=d&&!s((function(){var e=!1,n=/a/;return"split"===t&&((n={}).constructor={},n.constructor[l]=function(){return n},n.flags="",n[f]=/./[f]),n.exec=function(){return e=!0,null},n[f](""),!e}));if(!d||!p||n){var g=r(/./[f]),v=e(f,""[t],(function(t,e,n,o,s){var a=r(t),c=e.exec;return c===i||c===u.exec?d&&!s?{done:!0,value:g(e,n,o)}:{done:!0,value:a(n,e,o)}:{done:!1}}));o(String.prototype,t,v[0]),o(u,f,v[1])}h&&c(u[f],"sham",!0)}},3171:function(t,e,n){var r=n(7188),o=Function.prototype,i=o.apply,s=o.call;t.exports="object"==typeof Reflect&&Reflect.apply||(r?s.bind(i):function(){return s.apply(i,arguments)})},7188:function(t,e,n){var r=n(4229);t.exports=!r((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}))},266:function(t,e,n){var r=n(7188),o=Function.prototype.call;t.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},1805:function(t,e,n){var r=n(7400),o=n(8270),i=Function.prototype,s=r&&Object.getOwnPropertyDescriptor,a=o(i,"name"),c=a&&"something"===function(){}.name,l=a&&(!r||r&&s(i,"name").configurable);t.exports={EXISTS:a,PROPER:c,CONFIGURABLE:l}},5968:function(t,e,n){var r=n(7188),o=Function.prototype,i=o.bind,s=o.call,a=r&&i.bind(s,s);t.exports=r?function(t){return t&&a(t)}:function(t){return t&&function(){return s.apply(t,arguments)}}},1333:function(t,e,n){var r=n(9859),o=n(6733),i=function(t){return o(t)?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t]):r[t]&&r[t][e]}},5300:function(t,e,n){var r=n(7111);t.exports=function(t,e){var n=t[e];return null==n?void 0:r(n)}},17:function(t,e,n){var r=n(5968),o=n(2991),i=Math.floor,s=r("".charAt),a=r("".replace),c=r("".slice),l=/\$([$&'`]|\d{1,2}|<[^>]*>)/g,u=/\$([$&'`]|\d{1,2})/g;t.exports=function(t,e,n,r,h,f){var d=n+t.length,p=r.length,g=u;return void 0!==h&&(h=o(h),g=l),a(f,g,(function(o,a){var l;switch(s(a,0)){case"$":return"$";case"&":return t;case"`":return c(e,0,n);case"'":return c(e,d);case"<":l=h[c(a,1,-1)];break;default:var u=+a;if(0===u)return o;if(u>p){var f=i(u/10);return 0===f?o:f<=p?void 0===r[f-1]?s(a,1):r[f-1]+s(a,1):o}l=r[u-1]}return void 0===l?"":l}))}},9859:function(t,e,n){var r=function(t){return t&&t.Math==Math&&t};t.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof n.g&&n.g)||function(){return this}()||Function("return this")()},8270:function(t,e,n){var r=n(5968),o=n(2991),i=r({}.hasOwnProperty);t.exports=Object.hasOwn||function(t,e){return i(o(t),e)}},5977:function(t){t.exports={}},3777:function(t,e,n){var r=n(1333);t.exports=r("document","documentElement")},4394:function(t,e,n){var r=n(7400),o=n(4229),i=n(2635);t.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},9337:function(t,e,n){var r=n(5968),o=n(4229),i=n(7079),s=Object,a=r("".split);t.exports=o((function(){return!s("z").propertyIsEnumerable(0)}))?function(t){return"String"==i(t)?a(t,""):s(t)}:s},8511:function(t,e,n){var r=n(5968),o=n(6733),i=n(5353),s=r(Function.toString);o(i.inspectSource)||(i.inspectSource=function(t){return s(t)}),t.exports=i.inspectSource},6407:function(t,e,n){var r,o,i,s=n(8694),a=n(9859),c=n(5968),l=n(5052),u=n(5762),h=n(8270),f=n(5353),d=n(4399),p=n(5977),g="Object already initialized",v=a.TypeError,b=a.WeakMap;if(s||f.state){var m=f.state||(f.state=new b),y=c(m.get),w=c(m.has),E=c(m.set);r=function(t,e){if(w(m,t))throw new v(g);return e.facade=t,E(m,t,e),e},o=function(t){return y(m,t)||{}},i=function(t){return w(m,t)}}else{var S=d("state");p[S]=!0,r=function(t,e){if(h(t,S))throw new v(g);return e.facade=t,u(t,S,e),e},o=function(t){return h(t,S)?t[S]:{}},i=function(t){return h(t,S)}}t.exports={set:r,get:o,has:i,enforce:function(t){return i(t)?o(t):r(t,{})},getterFor:function(t){return function(e){var n;if(!l(e)||(n=o(e)).type!==t)throw v("Incompatible receiver, "+t+" required");return n}}}},6733:function(t){t.exports=function(t){return"function"==typeof t}},2359:function(t,e,n){var r=n(5968),o=n(4229),i=n(6733),s=n(1589),a=n(1333),c=n(8511),l=function(){},u=[],h=a("Reflect","construct"),f=/^\s*(?:class|function)\b/,d=r(f.exec),p=!f.exec(l),g=function(t){if(!i(t))return!1;try{return h(l,u,t),!0}catch(t){return!1}},v=function(t){if(!i(t))return!1;switch(s(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return p||!!d(f,c(t))}catch(t){return!0}};v.sham=!0,t.exports=!h||o((function(){var t;return g(g.call)||!g(Object)||!g((function(){t=!0}))||t}))?v:g},6541:function(t,e,n){var r=n(4229),o=n(6733),i=/#|\.prototype\./,s=function(t,e){var n=c[a(t)];return n==u||n!=l&&(o(e)?r(e):!!e)},a=s.normalize=function(t){return String(t).replace(i,".").toLowerCase()},c=s.data={},l=s.NATIVE="N",u=s.POLYFILL="P";t.exports=s},5052:function(t,e,n){var r=n(6733);t.exports=function(t){return"object"==typeof t?null!==t:r(t)}},4231:function(t){t.exports=!1},9395:function(t,e,n){var r=n(1333),o=n(6733),i=n(1321),s=n(6969),a=Object;t.exports=s?function(t){return"symbol"==typeof t}:function(t){var e=r("Symbol");return o(e)&&i(e.prototype,a(t))}},693:function(t,e,n){"use strict";var r,o,i,s=n(4229),a=n(6733),c=n(2391),l=n(7567),u=n(4768),h=n(95),f=n(4231),d=h("iterator"),p=!1;[].keys&&("next"in(i=[].keys())?(o=l(l(i)))!==Object.prototype&&(r=o):p=!0),null==r||s((function(){var t={};return r[d].call(t)!==t}))?r={}:f&&(r=c(r)),a(r[d])||u(r,d,(function(){return this})),t.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:p}},5495:function(t){t.exports={}},9646:function(t,e,n){var r=n(4237);t.exports=function(t){return r(t.length)}},6039:function(t,e,n){var r=n(4229),o=n(6733),i=n(8270),s=n(7400),a=n(1805).CONFIGURABLE,c=n(8511),l=n(6407),u=l.enforce,h=l.get,f=Object.defineProperty,d=s&&!r((function(){return 8!==f((function(){}),"length",{value:8}).length})),p=String(String).split("String"),g=t.exports=function(t,e,n){"Symbol("===String(e).slice(0,7)&&(e="["+String(e).replace(/^Symbol\(([^)]*)\)/,"$1")+"]"),n&&n.getter&&(e="get "+e),n&&n.setter&&(e="set "+e),(!i(t,"name")||a&&t.name!==e)&&f(t,"name",{value:e,configurable:!0}),d&&n&&i(n,"arity")&&t.length!==n.arity&&f(t,"length",{value:n.arity});try{n&&i(n,"constructor")&&n.constructor?s&&f(t,"prototype",{writable:!1}):t.prototype&&(t.prototype=void 0)}catch(t){}var r=u(t);return i(r,"source")||(r.source=p.join("string"==typeof e?e:"")),t};Function.prototype.toString=g((function(){return o(this)&&h(this).source||c(this)}),"toString")},917:function(t){var e=Math.ceil,n=Math.floor;t.exports=Math.trunc||function(t){var r=+t;return(r>0?n:e)(r)}},3839:function(t,e,n){var r=n(6358),o=n(4229);t.exports=!!Object.getOwnPropertySymbols&&!o((function(){var t=Symbol();return!String(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},8694:function(t,e,n){var r=n(9859),o=n(6733),i=n(8511),s=r.WeakMap;t.exports=o(s)&&/native code/.test(i(s))},6485:function(t,e,n){"use strict";var r=n(7111),o=function(t){var e,n;this.promise=new t((function(t,r){if(void 0!==e||void 0!==n)throw TypeError("Bad Promise constructor");e=t,n=r})),this.resolve=r(e),this.reject=r(n)};t.exports.f=function(t){return new o(t)}},2391:function(t,e,n){var r,o=n(1176),i=n(219),s=n(3837),a=n(5977),c=n(3777),l=n(2635),u=n(4399),h=u("IE_PROTO"),f=function(){},d=function(t){return"