diff --git a/CHANGELOG-WIP.md b/CHANGELOG-WIP.md index 2d7d4eeb66a..e56ddc40295 100644 --- a/CHANGELOG-WIP.md +++ b/CHANGELOG-WIP.md @@ -3,7 +3,8 @@ ### Content Management - Collapsed Matrix blocks now show their entries’ UI labels as preview text, whenever possible. ([#18484](https://github.com/craftcms/cms/discussions/18484)) - Element-level actions within nested element management fields (Matrix, Addresses, etc.) now consistently affect all selected elements, when performed on a selected element. ([#18561](https://github.com/craftcms/cms/pull/18561)) -- Elements within Matrix and Addresses fields now have “Paste above” actions when a compatible element is copied. ([#17406](https://github.com/craftcms/cms/discussions/17406)) +- Elements within Matrix and Addresses fields now have “Paste above” actions when a compatible element is copied. ([#17406](https://github.com/craftcms/cms/discussions/17406)) +- Elements now keep track of the index page’s URL their edit page was linked to from, and explicitly redirect back to that page after save, rather than always redirecting to the referrer. ([#18680](https://github.com/craftcms/cms/pull/18680)) - Addresses fields now have a “Copy all addresses” field-level action. ([#18561](https://github.com/craftcms/cms/pull/18561)) - Matrix fields’ “Expand”, “Collapse”, and “Copy” field-level actions now always affect all nested entries, regardless of whether any entries are selected. ([#18561](https://github.com/craftcms/cms/pull/18561)) - Matrix fields no longer have “Duplicate” and “Delete” field-level actions. ([#18561](https://github.com/craftcms/cms/pull/18561)) diff --git a/src/base/Element.php b/src/base/Element.php index 28b52e9e098..92627728428 100644 --- a/src/base/Element.php +++ b/src/base/Element.php @@ -80,6 +80,7 @@ use craft\helpers\Db; use craft\helpers\ElementHelper; use craft\helpers\Html; +use craft\helpers\Json; use craft\helpers\StringHelper; use craft\helpers\Template; use craft\helpers\UrlHelper; @@ -1285,6 +1286,7 @@ public static function indexHtml( 'nestedInputNamespace' => $viewState['nestedInputNamespace'] ?? null, 'tableName' => static::pluralDisplayName(), 'elementQuery' => self::elementQueryWithAllDescendants($elementQuery), + 'returnUrl' => $viewState['returnUrl'] ?? null, ]; $db = Craft::$app->getDb(); @@ -3940,12 +3942,20 @@ public function getAltActions(): array $elementsService = Craft::$app->getElements(); $canSaveCanonical = $elementsService->canSaveCanonical($this); + $returnUrl = Craft::$app->getRequest()->getQueryParam('returnUrl'); + $redirectParams = array_filter([ + 'returnUrl' => $returnUrl, + ]); + $altActions = [ [ 'label' => $isUnpublishedDraft && $canSaveCanonical ? Craft::t('app', 'Create and continue editing') : Craft::t('app', 'Save and continue editing'), 'redirect' => '{cpEditUrl}', + 'params' => array_filter([ + 'redirectParams' => !empty($redirectParams) ? Json::encode($redirectParams) : null, + ]), 'shortcut' => true, 'retainScroll' => true, 'eventData' => ['autosave' => false], @@ -3962,7 +3972,10 @@ public function getAltActions(): array 'shortcut' => true, 'shift' => true, 'eventData' => ['autosave' => false], - 'params' => ['addAnother' => 1], + 'params' => [ + 'addAnother' => 1, + 'returnUrl' => $returnUrl, + ], ]; } @@ -3987,6 +4000,7 @@ public function getAltActions(): array 'params' => [ 'asUnpublishedDraft' => true, 'deleteProvisionalDraft' => true, + 'redirectParams' => !empty($redirectParams) ? Json::encode($redirectParams) : null, ], ]; } diff --git a/src/controllers/ElementIndexesController.php b/src/controllers/ElementIndexesController.php index 139a1746c3c..755ab060501 100644 --- a/src/controllers/ElementIndexesController.php +++ b/src/controllers/ElementIndexesController.php @@ -884,6 +884,7 @@ protected function elementResponseData(bool $includeContainer, bool $includeActi [ ...$this->viewState, 'fieldLayouts' => $this->fieldLayouts, + 'returnUrl' => $this->request->getParam('returnUrl'), ], $this->sourceKey, $this->context, diff --git a/src/controllers/ElementsController.php b/src/controllers/ElementsController.php index d31ebc3add9..b048508d5be 100644 --- a/src/controllers/ElementsController.php +++ b/src/controllers/ElementsController.php @@ -364,7 +364,19 @@ public function actionEdit(?ElementInterface $element, ?int $elementId = null): [$docTitle, $title] = $this->_editElementTitles($element); $enabledForSite = $element->getEnabledForSite(); $hasRoute = $element->getRoute() !== null; - $redirectUrl = $this->request->getValidatedQueryParam('returnUrl') ?? UrlHelper::cpReferralUrl() ?? ElementHelper::postEditUrl($element); + + $redirectUrl = $this->request->getQueryParam('returnUrl'); + if ($redirectUrl) { + // only require the URL to be hashed if it contains Twig code + $validated = Craft::$app->getSecurity()->validateData($redirectUrl); + if ($validated !== false) { + $redirectUrl = $validated; + } elseif (str_contains($redirectUrl, '{')) { + throw new BadRequestHttpException("Invalid returnUrl param: $redirectUrl"); + } + } else { + $redirectUrl = ElementHelper::postEditUrl($element); + } // Site statuses if ($canEditMultipleSites) { @@ -1040,9 +1052,16 @@ private function _additionalButtons( // Revert content from this revision if ($isRevision && $canSaveCanonical && $element->hasRevisions()) { + $returnUrl = $this->request->getQueryParam('returnUrl'); $components[] = Html::beginForm() . Html::actionInput('elements/revert') . Html::redirectInput('{cpEditUrl}') . + ($returnUrl + ? Html::hiddenInput('redirectParams', Json::encode([ + 'returnUrl' => $returnUrl, + ])) + : '' + ) . Html::hiddenInput('elementId', (string)$canonical->id) . Html::hiddenInput('revisionId', (string)$element->revisionId) . Html::button(Craft::t('app', 'Revert content from this revision'), [ @@ -3012,6 +3031,11 @@ private function _asSuccess( ]); } + $returnUrl = $this->request->getParam('returnUrl'); + if ($returnUrl) { + $url = UrlHelper::urlWithParams($url, ['returnUrl' => $returnUrl]); + } + $response->redirect($url); } diff --git a/src/controllers/EntryTypesController.php b/src/controllers/EntryTypesController.php index 76acd1ff379..2239278b2b8 100644 --- a/src/controllers/EntryTypesController.php +++ b/src/controllers/EntryTypesController.php @@ -20,7 +20,6 @@ use craft\helpers\Cp; use craft\helpers\Html; use craft\helpers\StringHelper; -use craft\helpers\UrlHelper; use craft\models\EntryType; use craft\models\Section; use craft\web\Controller; @@ -125,7 +124,7 @@ public function actionEdit(?int $entryTypeId = null, ?EntryType $entryType = nul if (!$this->readOnly) { $response ->action('entry-types/save') - ->redirectUrl(UrlHelper::cpReferralUrl() ?? 'settings/entry-types') + ->redirectUrl('settings/entry-types') ->addAltAction(Craft::t('app', 'Save and continue editing'), [ 'redirect' => 'settings/entry-types/{id}', 'shortcut' => true, diff --git a/src/controllers/FieldsController.php b/src/controllers/FieldsController.php index 6659b1f1846..96a7948f5f8 100644 --- a/src/controllers/FieldsController.php +++ b/src/controllers/FieldsController.php @@ -205,7 +205,7 @@ public function actionEditField(?int $fieldId = null, ?FieldInterface $field = n if (!$this->readOnly) { $response ->action('fields/save-field') - ->redirectUrl(UrlHelper::cpReferralUrl() ?? 'settings/fields') + ->redirectUrl('settings/fields') ->addAltAction(Craft::t('app', 'Save and continue editing'), [ 'redirect' => 'settings/fields/edit/{id}', 'shortcut' => true, diff --git a/src/helpers/Cp.php b/src/helpers/Cp.php index adf2bec9adc..5b71b83354c 100644 --- a/src/helpers/Cp.php +++ b/src/helpers/Cp.php @@ -526,6 +526,7 @@ public static function chipHtml(Chippable $component, array $config = []): strin * - `class` – Class name(s) that should be added to the container element * - `context` – The context the chip is going to be shown in (`index`, `field`, etc.) * - `hyperlink` – Whether the chip label should be hyperlinked to the element’s URL + * - `returnUrl` – The `returnUrl` param that should be added to the hyperlink URL * - `id` – The chip’s `id` attribute * - `inputName` – The `name` attribute that should be set on a hidden input, if set * - `inputValue` – The `value` attribute that should be set on the hidden input, if `inputName` is set. Defaults to [[\craft\base\Identifiable::getId()`]]. @@ -555,6 +556,7 @@ public static function elementChipHtml(ElementInterface $element, array $config 'attributes' => [], 'autoReload' => true, 'context' => 'index', + 'returnUrl' => null, 'id' => sprintf('chip-%s', mt_rand()), 'inputName' => null, 'selectable' => false, @@ -574,6 +576,7 @@ public static function elementChipHtml(ElementInterface $element, array $config 'data' => array_filter([ 'settings' => $config['autoReload'] ? [ 'context' => $config['context'], + 'returnUrl' => $config['returnUrl'], 'showDraftName' => $config['showDraftName'], 'showProvisionalDraftLabel' => $config['showProvisionalDraftLabel'], ] : false, @@ -629,6 +632,7 @@ public static function elementChipHtml(ElementInterface $element, array $config * - `autoReload` – Whether the card should auto-reload itself when it’s saved * - `context` – The context the card is going to be shown in (`index`, `field`, etc.) * - `hyperlink` – Whether the card label should be hyperlinked to the element’s URL + * - `returnUrl` – The `returnUrl` param that should be added to the hyperlink URL * - `id` – The card’s `id` attribute * - `inputName` – The `name` attribute that should be set on the hidden input, if `context` is set to `field` * - `selectable` – Whether the card should include a checkbox input @@ -648,6 +652,7 @@ public static function elementCardHtml(ElementInterface $element, array $config 'autoReload' => true, 'context' => 'index', 'hyperlink' => false, + 'returnUrl' => null, 'id' => sprintf('card-%s', mt_rand()), 'inputName' => null, 'selectable' => false, @@ -728,6 +733,7 @@ public static function elementCardHtml(ElementInterface $element, array $config 'data' => array_filter([ 'settings' => $config['autoReload'] ? [ 'hyperlink' => $config['hyperlink'], + 'returnUrl' => $config['returnUrl'], 'selectable' => $config['selectable'], 'context' => $config['context'], 'id' => Craft::$app->getView()->namespaceInputId($config['id']), @@ -1154,6 +1160,16 @@ private static function elementLabelHtml(ElementInterface $element, array $confi $config['context'] !== 'modal' && ($url = $attributes['data']['cp-url'] ?? null) ) { + $returnUrl = $config['returnUrl'] ?? null; + if ($returnUrl) { + if (str_contains($returnUrl, '{')) { + $returnUrl = Craft::$app->getSecurity()->hashData($returnUrl); + } + $url = UrlHelper::urlWithParams($url, [ + 'returnUrl' => $returnUrl, + ]); + } + $content = Html::tag('a', Html::tag('span', $content), [ 'class' => ['label-link'], 'href' => $url, diff --git a/src/helpers/UrlHelper.php b/src/helpers/UrlHelper.php index 1df8d2a59d7..315fc026d3e 100644 --- a/src/helpers/UrlHelper.php +++ b/src/helpers/UrlHelper.php @@ -579,6 +579,7 @@ public static function cpHost(): string * * @return string|null * @since 5.9.0 + * @deprecated in 5.10.0 */ public static function cpReferralUrl(): ?string { diff --git a/src/templates/_elements/cardsview/elements.twig b/src/templates/_elements/cardsview/elements.twig index d20da447a5c..c65f5e9fb21 100644 --- a/src/templates/_elements/cardsview/elements.twig +++ b/src/templates/_elements/cardsview/elements.twig @@ -1,5 +1,6 @@ {% set context = context ?? 'index' %} {% set hyperlink = hyperlink ?? (context in ['index', 'embedded-index']) %} +{% set returnUrl = returnUrl ?? null %} {% apply spaceless %} {% for element in elements %} @@ -14,6 +15,7 @@ selectable, sortable, hyperlink, + returnUrl, }) }} {% endtag %} {% endfor %} diff --git a/src/templates/_elements/tableview/elements.twig b/src/templates/_elements/tableview/elements.twig index 08f1457bc2e..808ddb34f8b 100644 --- a/src/templates/_elements/tableview/elements.twig +++ b/src/templates/_elements/tableview/elements.twig @@ -8,6 +8,7 @@ {% set showHeaderColumn = showHeaderColumn ?? false %} {% set context = context ?? 'index' %} {% set hyperlink = hyperlink ?? (context in ['index', 'embedded-index']) %} +{% set returnUrl = returnUrl ?? null %} {% for element in elements %} {% set totalDescendants = structure @@ -90,6 +91,7 @@ class: ['chromeless'], }, hyperlink, + returnUrl, }) %} {% if not showHeaderColumn %} {% set chip = chip|attr({class: 'hide-label'}) %} diff --git a/src/templates/_elements/thumbsview/elements.twig b/src/templates/_elements/thumbsview/elements.twig index b86b7f1202f..bead4c338fd 100644 --- a/src/templates/_elements/thumbsview/elements.twig +++ b/src/templates/_elements/thumbsview/elements.twig @@ -1,5 +1,6 @@ {% set context = context ?? 'index' %} {% set hyperlink = hyperlink ?? (context in ['index', 'embedded-index']) %} +{% set returnUrl = returnUrl ?? null %} {% apply spaceless %} {% for element in elements %} @@ -15,6 +16,7 @@ selectable: selectable, sortable: sortable, hyperlink, + returnUrl, }) }} {% endtag %} {% endfor %} diff --git a/src/web/Controller.php b/src/web/Controller.php index 86812ee3cf1..40d9d2e6594 100644 --- a/src/web/Controller.php +++ b/src/web/Controller.php @@ -14,6 +14,8 @@ use craft\elements\User; use craft\events\DefineBehaviorsEvent; use craft\helpers\Cp; +use craft\helpers\Json; +use craft\helpers\UrlHelper; use yii\base\Action; use yii\base\InvalidArgumentException; use yii\base\InvalidConfigException; @@ -650,6 +652,17 @@ protected function getPostedRedirectUrl(?object $object = null): ?string $url = $this->getView()->renderObjectTemplate($url, $object); } + $params = $this->request->getBodyParam('redirectParams'); + if ($params) { + try { + $params = Json::decode($params); + } catch (InvalidArgumentException $e) { + throw new BadRequestHttpException($e->getMessage(), previous: $e); + } + + $url = UrlHelper::urlWithParams($url, $params); + } + return $url; } diff --git a/src/web/assets/cp/dist/cp.js b/src/web/assets/cp/dist/cp.js index fd599e683b0..30f25ce376d 100644 --- a/src/web/assets/cp/dist/cp.js +++ b/src/web/assets/cp/dist/cp.js @@ -1,3 +1,3 @@ /*! For license information please see cp.js.LICENSE.txt */ -(function(){var __webpack_modules__={0:function(){function t(t,n){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=n){var i,r,a,s,o=[],l=!0,c=!1;try{if(a=(n=n.call(t)).next,0===e){if(Object(n)!==n)return;l=!1}else for(;!(l=(i=a.call(n)).done)&&(o.push(i.value),o.length!==e);l=!0);}catch(t){c=!0,r=t}finally{try{if(!l&&null!=n.return&&(s=n.return(),Object(s)!==s))return}finally{if(c)throw r}}return o}}(t,n)||function(t,n){if(t){if("string"==typeof t)return e(t,n);var i={}.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?e(t,n):void 0}}(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function e(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=Array(e);nn.settings.maxFileSize&&(n._rejectedFiles.size.push("“"+t.name+"”"),r=!1),r&&"function"==typeof n.settings.canAddMoreFiles&&!n.settings.canAddMoreFiles(n._validFileCounter)&&(n._rejectedFiles.limit.push("“"+t.name+"”"),r=!1),r&&(n._validFileCounter++,e.submit()),++n._totalFileCounter===e.originalFiles.length&&(n._totalFileCounter=0,n._validFileCounter=0,n.processErrorMessages())})),!0},destroy:function(){var e=this;this.uploader.fileupload("instance")&&this.uploader.fileupload("destroy"),this.$element.off("fileuploadadd",this._onFileAdd),Object.entries(this.events).forEach((function(n){var i=t(n,2),r=i[0],a=i[1];e.$element.off(r,a)}))}},{defaults:{autoUpload:!1,sequentialUploads:!0,maxFileSize:Craft.maxUploadSize,replaceFileInput:!1,createAction:"assets/upload",replaceAction:"assets/replace-file",deleteAction:"assets/delete-asset"}})},9:function(){Craft.Structure=Garnish.Base.extend({id:null,$container:null,state:null,structureDrag:null,init:function(t,e,n){this.id=t,this.$container=$(e),this.setSettings(n,Craft.Structure.defaults),this.$container.data("structure")&&(console.warn("Double-instantiating a structure on an element"),this.$container.data("structure").destroy()),this.$container.data("structure",this),this.state={},this.settings.storageKey&&$.extend(this.state,Craft.getLocalStorage(this.settings.storageKey,{})),void 0===this.state.collapsedElementIds&&(this.state.collapsedElementIds=[]);for(var i=this.$container.find("ul").prev(".row"),r=0;r').prependTo(a);-1!==$.inArray(a.children(".element").data("id"),this.state.collapsedElementIds)&&s.addClass("collapsed"),this.initToggle(o)}this.settings.sortable&&(this.structureDrag=new Craft.StructureDrag(this,this.settings.maxLevels)),this.settings.newChildUrl&&this.initNewChildMenus(this.$container.find(".add"))},initToggle:function(t){var e=this;t.on("click",(function(t){var n=$(t.currentTarget).closest("li"),i=n.children(".row").find(".element:first").data("id"),r=$.inArray(i,e.state.collapsedElementIds);n.hasClass("collapsed")?(n.removeClass("collapsed"),-1!==r&&e.state.collapsedElementIds.splice(r,1)):(n.addClass("collapsed"),-1===r&&e.state.collapsedElementIds.push(i)),e.settings.storageKey&&Craft.setLocalStorage(e.settings.storageKey,e.state)}))},initNewChildMenus:function(t){this.addListener(t,"click","onNewChildMenuClick")},onNewChildMenuClick:function(t){var e=$(t.currentTarget);if(!e.data("menubtn")){var n=e.parent().children(".element").data("id"),i=Craft.getUrl(this.settings.newChildUrl,"parentId="+n);$('").insertAfter(e),new Garnish.MenuBtn(e).showMenu()}},getIndent:function(t){return Craft.Structure.baseIndent+(t-1)*Craft.Structure.nestedIndent},addElement:function(t){var e=$('
  • ').appendTo(this.$container),n=$('
    ').appendTo(e);if(n.append(t),this.settings.sortable&&(n.append(''),this.structureDrag.addItems(e)),this.settings.newChildUrl){var i=$('').appendTo(n);this.initNewChildMenus(i)}n.css("margin-bottom",-30),n.velocity({"margin-bottom":0},"fast")},removeElement:function(t){var e,n=this,i=t.parent().parent();this.settings.sortable&&this.structureDrag.removeItems(i),i.siblings().length||(e=i.parent()),i.css("visibility","hidden").velocity({marginBottom:-i.height()},"fast",(function(){i.remove(),void 0!==e&&n._removeUl(e)}))},_removeUl:function(t){t.siblings(".row").children(".toggle").remove(),t.remove()},destroy:function(){this.$container.removeData("structure"),this.base()}},{baseIndent:8,nestedIndent:35,defaults:{storageKey:null,sortable:!1,newChildUrl:null,maxLevels:null}})},146:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}function e(){"use strict";e=function(){return i};var n,i={},r=Object.prototype,a=r.hasOwnProperty,s=Object.defineProperty||function(t,e,n){t[e]=n.value},o="function"==typeof Symbol?Symbol:{},l=o.iterator||"@@iterator",c=o.asyncIterator||"@@asyncIterator",u=o.toStringTag||"@@toStringTag";function h(t,e,n){return Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{h({},"")}catch(n){h=function(t,e,n){return t[e]=n}}function d(t,e,n,i){var r=e&&e.prototype instanceof b?e:b,a=Object.create(r.prototype),o=new A(i||[]);return s(a,"_invoke",{value:T(t,n,o)}),a}function f(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(t){return{type:"throw",arg:t}}}i.wrap=d;var p="suspendedStart",g="suspendedYield",m="executing",v="completed",y={};function b(){}function w(){}function C(){}var $={};h($,l,(function(){return this}));var _=Object.getPrototypeOf,S=_&&_(_(P([])));S&&S!==r&&a.call(S,l)&&($=S);var x=C.prototype=b.prototype=Object.create($);function I(t){["next","throw","return"].forEach((function(e){h(t,e,(function(t){return this._invoke(e,t)}))}))}function E(e,n){function i(r,s,o,l){var c=f(e[r],e,s);if("throw"!==c.type){var u=c.arg,h=u.value;return h&&"object"==t(h)&&a.call(h,"__await")?n.resolve(h.__await).then((function(t){i("next",t,o,l)}),(function(t){i("throw",t,o,l)})):n.resolve(h).then((function(t){u.value=t,o(u)}),(function(t){return i("throw",t,o,l)}))}l(c.arg)}var r;s(this,"_invoke",{value:function(t,e){function a(){return new n((function(n,r){i(t,e,n,r)}))}return r=r?r.then(a,a):a()}})}function T(t,e,i){var r=p;return function(a,s){if(r===m)throw Error("Generator is already running");if(r===v){if("throw"===a)throw s;return{value:n,done:!0}}for(i.method=a,i.arg=s;;){var o=i.delegate;if(o){var l=D(o,i);if(l){if(l===y)continue;return l}}if("next"===i.method)i.sent=i._sent=i.arg;else if("throw"===i.method){if(r===p)throw r=v,i.arg;i.dispatchException(i.arg)}else"return"===i.method&&i.abrupt("return",i.arg);r=m;var c=f(t,e,i);if("normal"===c.type){if(r=i.done?v:g,c.arg===y)continue;return{value:c.arg,done:i.done}}"throw"===c.type&&(r=v,i.method="throw",i.arg=c.arg)}}}function D(t,e){var i=e.method,r=t.iterator[i];if(r===n)return e.delegate=null,"throw"===i&&t.iterator.return&&(e.method="return",e.arg=n,D(t,e),"throw"===e.method)||"return"!==i&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+i+"' method")),y;var a=f(r,t.iterator,e.arg);if("throw"===a.type)return e.method="throw",e.arg=a.arg,e.delegate=null,y;var s=a.arg;return s?s.done?(e[t.resultName]=s.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=n),e.delegate=null,y):s:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,y)}function k(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function L(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function A(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(k,this),this.reset(!0)}function P(e){if(e||""===e){var i=e[l];if(i)return i.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var r=-1,s=function t(){for(;++r=0;--r){var s=this.tryEntries[r],o=s.completion;if("root"===s.tryLoc)return i("end");if(s.tryLoc<=this.prev){var l=a.call(s,"catchLoc"),c=a.call(s,"finallyLoc");if(l&&c){if(this.prev=0;--n){var i=this.tryEntries[n];if(i.tryLoc<=this.prev&&a.call(i,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),L(n),y}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var i=n.completion;if("throw"===i.type){var r=i.arg;L(n)}return r}}throw Error("illegal catch attempt")},delegateYield:function(t,e,i){return this.delegate={iterator:P(t),resultName:e,nextLoc:i},"next"===this.method&&(this.arg=n),y}},i}function n(t,e,n,i,r,a,s){try{var o=t[a](s),l=o.value}catch(t){return void n(t)}o.done?e(l):Promise.resolve(l).then(i,r)}var i,r;Craft.EntrySelectInput=Craft.BaseElementSelectInput.extend({get section(){var t=this;return this.settings.sectionId?Craft.publishableSections.find((function(e){return e.id===t.settings.sectionId})):null},canCreateElements:function(){return!!this.section},createElement:(i=e().mark((function t(n){var i,r;return e().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,Craft.sendActionRequest("POST","entries/create",{data:{siteId:this.settings.criteria.siteId,section:this.section.handle,authorId:Craft.userId,title:n}});case 2:return i=t.sent,r=i.data.entry,t.prev=4,t.next=7,this.showElementEditor(r);case 7:t.next=12;break;case 9:return t.prev=9,t.t0=t.catch(4),t.abrupt("return",null);case 12:return t.abrupt("return",r.id);case 13:case"end":return t.stop()}}),t,this,[[4,9]])})),r=function(){var t=this,e=arguments;return new Promise((function(r,a){var s=i.apply(t,e);function o(t){n(s,r,a,o,l,"next",t)}function l(t){n(s,r,a,o,l,"throw",t)}o(void 0)}))},function(t){return r.apply(this,arguments)}),showElementEditor:function(t){var e=this;return new Promise((function(n,i){var r=Craft.createElementEditor("craft\\elements\\Entry",{siteId:e.settings.criteria.siteId,elementId:t.id,draftId:t.draftId,params:{fresh:1}}),a=!1;r.on("submit",(function(){a=!0,n()})),r.on("close",(function(){a||i()}))}))}})},258:function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}function e(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function n(t){for(var n=1;n').appendTo(Garnish.$bod),this.$body=$('
    ').appendTo(this.$container),this.$footer=$('
  • ").appendTo(i);var a=new Garnish.MenuBtn(this.$selectTransformBtn,{onOptionSelect:this.onSelectTransform.bind(this)});a.disable(),this.$selectTransformBtn.data("menuButton",a)}},onSelectionChange:function(t){var e=!1;this.elementIndex.getSelectedElements().length&&this.settings.transforms.length&&(e=!0);var n=null;this.$selectTransformBtn&&(n=this.$selectTransformBtn.data("menuButton")),e?(n&&n.enable(),this.$selectTransformBtn.removeClass("disabled")):this.$selectTransformBtn&&(n&&n.disable(),this.$selectTransformBtn.addClass("disabled")),this.base()},onSelectTransform:function(t){var e=$(t).data("transform");this.selectImagesWithTransform(e)},selectImagesWithTransform:function(t){var e=this;void 0===Craft.AssetSelectorModal.transformUrls[t]&&(Craft.AssetSelectorModal.transformUrls[t]={});for(var n=this.elementIndex.getSelectedElements(),i=[],r=0;r",{class:"modal elementselectormodal","aria-labelledby":n}).appendTo(Garnish.$bod),r=$("
    ",{class:this.settings.showTitle?"header":"visually-hidden"}).appendTo(i);$("

    ",{id:n,text:this.settings.modalTitle}).appendTo(r);var a=$("
    ",{class:"body"}).append($("
    ",{class:"spinner big"})).appendTo(i);this.$footer=$("
    ",{class:"footer"}).appendTo(i),this.settings.fullscreen&&(i.addClass("fullscreen"),this.settings.minGutter=0),this.base(i,this.settings),this.$secondaryButtons=$('
    ').appendTo(this.$footer),this.$primaryButtons=$('
    ').appendTo(this.$footer),this.$cancelBtn=$("
    ").appendTo(r),s=$('
    ').appendTo(a),o=$("
    ').appendTo(this.$container),this.$cursor=$('
    ').appendTo(this.$container),this.$graduations=$('
    ').appendTo(this.$container),this.$graduationsUl=$("
      ").attr({"aria-hidden":"true"}).appendTo(this.$graduations),this.$container.attr({role:"slider",tabindex:"0","aria-valuemin":this.slideMin,"aria-valuemax":this.slideMax,"aria-valuenow":"0","aria-valuetext":Craft.t("app","{num, number} {num, plural, =1{degree} other{degrees}}",{num:0})});for(var i=this.graduationsMin;i<=this.graduationsMax;i++){var r=$('
    • '+i+"
    • ").appendTo(this.$graduationsUl);i%5==0&&r.addClass("main-graduation"),0===i&&r.addClass("selected")}this.$options=this.$container.find(".graduation"),this.addListener(this.$container,"resize",this._handleResize.bind(this)),this.addListener(this.$container,"tapstart",this._handleTapStart.bind(this)),this.addListener(Garnish.$bod,"tapmove",this._handleTapMove.bind(this)),this.addListener(Garnish.$bod,"tapend",this._handleTapEnd.bind(this)),this.addListener(this.$container,"keydown",this._handleKeypress.bind(this)),setTimeout((function(){n.graduationsCalculatedWidth=10*(n.$options.length-1),n.$graduationsUl.css("left",-n.graduationsCalculatedWidth/2+n.$container.width()/2)}),50)},_handleResize:function(){var t=this.valueToPosition(this.value);this.$graduationsUl.css("left",t)},_handleKeypress:function(t){var e=parseInt(this.$container.attr("aria-valuenow"),10);switch(t.keyCode){case Garnish.UP_KEY:case Garnish.RIGHT_KEY:this.setValue(e+1);break;case Garnish.DOWN_KEY:case Garnish.LEFT_KEY:this.setValue(e-1);break;case Garnish.PAGE_UP_KEY:this.setValue(e+10);break;case Garnish.PAGE_DOWN_KEY:this.setValue(e-10);break;case Garnish.HOME_KEY:this.setValue(this.slideMin);break;case Garnish.END_KEY:this.setValue(this.slideMax)}this.onChange()},_handleTapStart:function(t,e){t.preventDefault(),this.rotateIntent=$(t.target).is(".graduations *"),this.rotateIntent&&(this.startPositionX=e.position.x,this.startLeft=this.$graduationsUl.position().left,this.onStart())},_handleTapMove:function(t,e){this.rotateIntent&&Math.abs(e.position.x-this.startPositionX)>this.sensitivity&&(this.dragging=!0,this.$container.addClass("dragging"),t.preventDefault(),this._setValueFromTouch(e),this.onChange())},_setValueFromTouch:function(t){var e,n=this.dragging?this.startPositionX:this.$cursor.offset().left+this.$cursor.outerWidth()/2;e=this.dragging?n-t.position.x:t.position.x-n;var i=this.startLeft-e,r=this.positionToValue(i);this.setValue(r)},setValue:function(t){var e=this.valueToPosition(t);tthis.slideMax&&(t=this.slideMax,e=this.valueToPosition(t)),this.$graduationsUl.css("left",e),t>=this.slideMin&&t<=this.slideMax&&(this.$options.removeClass("selected"),$.each(this.$options,(function(e,n){$(n).data("graduation")>0&&$(n).data("graduation")<=t&&$(n).addClass("selected"),$(n).data("graduation")<0&&$(n).data("graduation")>=t&&$(n).addClass("selected"),0==$(n).data("graduation")&&$(n).addClass("selected")}))),this.$container.attr({"aria-valuenow":t,"aria-valuetext":Craft.t("app","{num, number} {num, plural, =1{degree} other{degrees}}",{num:parseInt(t,10)})}),this.value=t},_handleTapEnd:function(t,e){this.rotateIntent&&(this.dragging?(t.preventDefault(),this.dragging=!1,this.$container.removeClass("dragging")):(this._setValueFromTouch(e),this.onChange()),this.onEnd(),this.startPositionX=null,this.rotateIntent=!1)},positionToValue:function(t){var e=-1*this.graduationsMin,n=-1*(this.graduationsMin-this.graduationsMax);return(this.$graduations.width()/2+-1*t)/this.graduationsCalculatedWidth*n-e},valueToPosition:function(t){var e=-1*this.graduationsMin,n=-1*(this.graduationsMin-this.graduationsMax);return-((t+e)*this.graduationsCalculatedWidth/n-this.$graduations.width()/2)},onStart:function(){"function"==typeof this.settings.onChange&&this.settings.onStart(this)},onChange:function(){"function"==typeof this.settings.onChange&&this.settings.onChange(this)},onEnd:function(){"function"==typeof this.settings.onChange&&this.settings.onEnd(this)},defaultSettings:{onStart:$.noop,onChange:$.noop,onEnd:$.noop}})},3254:function(){},3517:function(){Craft.BaseUploader=Garnish.Base.extend({allowedKinds:null,$element:null,$fileInput:null,settings:null,fsType:null,formData:{},events:{},_rejectedFiles:{},_extensionList:null,_inProgressCounter:0,init:function(t,e){this._rejectedFiles={size:[],type:[],limit:[]},this.$element=t,this.settings=$.extend({},Craft.BaseUploader.defaults,e),this.formData=this.settings.formData,this.$fileInput=this.settings.fileInput||t,this.events=this.settings.events,this.settings.url||(this.settings.url=this.settings.replace?Craft.getActionUrl(this.settings.replaceAction):Craft.getActionUrl(this.settings.createAction)),this.settings.allowedKinds&&this.settings.allowedKinds.length&&("string"==typeof this.settings.allowedKinds&&(this.settings.allowedKinds=[this.settings.allowedKinds]),this.allowedKinds=this.settings.allowedKinds,delete this.settings.allowedKinds)},setParams:function(t){void 0!==Craft.csrfTokenName&&void 0!==Craft.csrfTokenValue&&(t[Craft.csrfTokenName]=Craft.csrfTokenValue),this.formData=t},getInProgress:function(){return this._inProgressCounter},isLastUpload:function(){return this.getInProgress()<2},processErrorMessages:function(){var t;this._rejectedFiles.type.length&&(t=1===this._rejectedFiles.type.length?"The file {files} could not be uploaded. The allowed file kinds are: {kinds}.":"The files {files} could not be uploaded. The allowed file kinds are: {kinds}.",t=Craft.t("app",t,{files:this._rejectedFiles.type.join(", "),kinds:this.allowedKinds.join(", ")}),this._rejectedFiles.type=[],Craft.cp.displayError(t)),this._rejectedFiles.size.length&&(t=1===this._rejectedFiles.size.length?"The file {files} could not be uploaded, because it exceeds the maximum upload size of {size}.":"The files {files} could not be uploaded, because they exceeded the maximum upload size of {size}.",t=Craft.t("app",t,{files:this._rejectedFiles.size.join(", "),size:this.humanFileSize(this.settings.maxFileSize)}),this._rejectedFiles.size=[],Craft.cp.displayError(t)),this._rejectedFiles.limit.length&&(t=1===this._rejectedFiles.limit.length?"The file {files} could not be uploaded, because the field limit has been reached.":"The files {files} could not be uploaded, because the field limit has been reached.",t=Craft.t("app",t,{files:this._rejectedFiles.limit.join(", ")}),this._rejectedFiles.limit=[],Craft.cp.displayError(t))},humanFileSize:function(t){var e=1024;if(t=e);return t.toFixed(1)+" "+["kB","MB","GB","TB","PB","EB","ZB","YB"][n]},_createExtensionList:function(){this._extensionList=[];for(var t=0;t=0;--r){var s=this.tryEntries[r],o=s.completion;if("root"===s.tryLoc)return i("end");if(s.tryLoc<=this.prev){var l=a.call(s,"catchLoc"),c=a.call(s,"finallyLoc");if(l&&c){if(this.prev=0;--n){var i=this.tryEntries[n];if(i.tryLoc<=this.prev&&a.call(i,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),L(n),y}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var i=n.completion;if("throw"===i.type){var r=i.arg;L(n)}return r}}throw Error("illegal catch attempt")},delegateYield:function(t,e,i){return this.delegate={iterator:P(t),resultName:e,nextLoc:i},"next"===this.method&&(this.arg=n),y}},i}function n(t,e,n,i,r,a,s){try{var o=t[a](s),l=o.value}catch(t){return void n(t)}o.done?e(l):Promise.resolve(l).then(i,r)}Craft.AssetSelectInput=Craft.BaseElementSelectInput.extend({$uploadBtn:null,uploader:null,progressBar:null,openPreviewTimeout:null,init:function(){this.base.apply(this,arguments),this.settings.canUpload&&this._attachUploader(),this.updateAddElementsBtn(),this.addListener(this.$elementsContainer,"keydown",this._onKeyDown.bind(this))},elementSelectSettings:function(){return Object.assign(this.base(),{makeFocusable:!0})},_onKeyDown:function(t){if(t.keyCode===Garnish.SPACE_KEY&&t.shiftKey)return this.openPreview(),t.stopPropagation(),!1},clearOpenPreviewTimeout:function(){this.openPreviewTimeout&&(clearTimeout(this.openPreviewTimeout),this.openPreviewTimeout=null)},openPreview:function(t){Craft.PreviewFileModal.openInstance?Craft.PreviewFileModal.openInstance.hide():(t||(t=this.$elements.filter(":focus").add(this.$elements.has(":focus"))),t.length&&Craft.PreviewFileModal.showForAsset(t,this.elementSelect))},_attachUploader:function(){var t=this;this.progressBar=new Craft.ProgressBar($('
      ').appendTo(this.$container)),this.$addElementBtn&&(this.$uploadBtn=$("
      ').addClass().appendTo(Garnish.$bod)),this.$prompt=$('
      ').appendTo(this.$modalContainerDiv.empty()),this.$promptMessage=$('

      ').appendTo(this.$prompt),this.$promptChoices=$('

      ').appendTo(this.$prompt),this.$promptApplyToRemainingContainer=$('
      ",{class:"entry-type-override-settings-body"}),$("
      ",{class:"fields",html:t.settingsHtml}).appendTo(n),i=$("
      ",{class:"entry-type-override-settings-footer"}),$("
      ",{class:"flex-grow"}).appendTo(i),r=Craft.ui.createButton({label:Craft.t("app","Close"),spinner:!0}).appendTo(i),Craft.ui.createSubmitButton({class:"secondary",label:Craft.t("app","Apply"),spinner:!0}).appendTo(i),a=n.add(i),(o=new Craft.Slideout(a,{containerElement:"form",containerAttributes:{action:"",method:"post",novalidate:"",class:"entry-type-override-settings"}})).on("open",(function(){Garnish.requestAnimationFrame((function(){o.$container.find(".text:first").focus()}))})),r.on("click",(function(){o.close()})),!t.headHtml){e.next=13;break}return e.next=13,Craft.appendHeadHtml(t.headHtml);case 13:if(!t.bodyHtml){e.next=16;break}return e.next=16,Craft.appendBodyHtml(t.bodyHtml);case 16:return Craft.initUiElements(o.$container),e.abrupt("return",o);case 18:case"end":return e.stop()}}),e)})))()},applySettings:function(t,e,i){var a=this;return l(s().mark((function o(){var l,c,u,h,d,f,p,g,m,v;return s().wrap((function(s){for(;;)switch(s.prev=s.next){case 0:return l=e.$container.find("button[type=submit]").addClass("loading"),e.$container.find(".field.has-errors").each((function(t,e){var n=$(e);n.removeClass("has-errors"),n.children(".input").removeClass("errors prevalidate"),n.children("ul.errors").remove()})),s.prev=2,s.prev=3,s.next=6,Craft.sendActionRequest("POST","entry-types/apply-override-settings",{data:{id:t.data("id"),settingsNamespace:i,settings:e.$container.serialize()}});case 6:u=s.sent,c=u.data,s.next=16;break;case 10:throw s.prev=10,s.t0=s.catch(3),(f=null===s.t0||void 0===s.t0||null===(h=s.t0.response)||void 0===h||null===(h=h.data)||void 0===h?void 0:h.errors)&&Object.entries(f).forEach((function(t){var n=r(t,2),i=n[0],a=n[1],s=e.$container.find('[data-error-key="'.concat(i,'"]'));s.length&&Craft.ui.addErrorsToField(s,a)})),Craft.cp.displayError(null===s.t0||void 0===s.t0||null===(d=s.t0.response)||void 0===d||null===(d=d.data)||void 0===d?void 0:d.message),s.t0;case 16:p=$(c.chipHtml),t.find(".chip-label").replaceWith(p.find(".chip-label")),g=t.find("input"),m=n({},c.config),(v=JSON.parse(g.val()).group)&&(m.group=v),g.val(JSON.stringify(m)),Craft.initUiElements(t),a.trigger("applySettings"),e.close(),e.destroy();case 27:return s.prev=27,l.removeClass("loading"),s.finish(27);case 30:case"end":return s.stop()}}),o,null,[[2,,27,30],[3,10]])})))()},renderSettings:function(t){return Object.assign(this.base(),{inputValue:this.settings.allowOverrides?JSON.stringify({id:t}):null})}},{defaults:{allowOverrides:!1}})},4004:function(){Craft.ProgressBar=Garnish.Base.extend({$progressBar:null,$innerProgressBar:null,$progressBarStatus:null,intervalManager:null,_itemCount:0,_progressPercentage:null,_processedItemCount:0,_displaySteps:!1,init:function(t,e,n){var i=this;this.setSettings(n,Craft.ProgressBar.defaults),e&&(this._displaySteps=!0),this.$progressBar=$('