From 28fabc63a988a5989104c06691bee19a68682b70 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Mon, 29 Dec 2025 17:20:26 -0800 Subject: [PATCH 1/7] Support including nested content block fields in cards --- src/fieldlayoutelements/BaseField.php | 23 ++++- src/fieldlayoutelements/CustomField.php | 28 ++++++ src/helpers/Cp.php | 93 +++++++++++++----- src/models/FieldLayout.php | 54 ++++++++++- src/web/assets/cp/dist/cp.js | 2 +- src/web/assets/cp/dist/cp.js.map | 2 +- .../assets/cp/src/js/FieldLayoutDesigner.js | 95 +++++++------------ 7 files changed, 202 insertions(+), 95 deletions(-) diff --git a/src/fieldlayoutelements/BaseField.php b/src/fieldlayoutelements/BaseField.php index ab62dee9e74..ab01f69c7e4 100644 --- a/src/fieldlayoutelements/BaseField.php +++ b/src/fieldlayoutelements/BaseField.php @@ -66,6 +66,7 @@ abstract class BaseField extends FieldLayoutElement /** * @var bool Whether this field’s contents should be included in element cards. * @since 5.0.0 + * @deprecated in 5.9.0 */ public bool $includeInCards = false; @@ -166,6 +167,26 @@ public function previewable(): bool return false; } + /** + * Returns the card preview options supplied by this field. + * + * @return array|null + * @since 5.9.0 + */ + public function getPreviewOptions(): ?array + { + if (!$this->previewable()) { + return null; + } + + return [ + [ + 'label' => $this->selectorLabel() ?? $this->attribute(), + 'value' => "layoutElement:{uid}", + ], + ]; + } + /** * @inheritdoc */ @@ -244,7 +265,7 @@ protected function selectorAttributes(): array 'mandatory' => $this->mandatory(), 'requirable' => $this->requirable(), 'thumbable' => $this->thumbable(), - 'previewable' => $this->previewable(), + 'preview-options' => $this->getPreviewOptions(), ], ]; } diff --git a/src/fieldlayoutelements/CustomField.php b/src/fieldlayoutelements/CustomField.php index a98d6e809b2..bd784a42af9 100644 --- a/src/fieldlayoutelements/CustomField.php +++ b/src/fieldlayoutelements/CustomField.php @@ -18,6 +18,7 @@ use craft\elements\conditions\users\UserCondition; use craft\elements\User; use craft\errors\FieldNotFoundException; +use craft\fields\ContentBlock; use craft\helpers\ArrayHelper; use craft\helpers\Cp; use craft\helpers\Html; @@ -212,6 +213,33 @@ public function previewable(): bool return $field instanceof PreviewableFieldInterface; } + /** + * @inheritdoc + */ + public function getPreviewOptions(): ?array + { + try { + $field = $this->getField(); + } catch (FieldNotFoundException) { + return null; + } + + if ($field instanceof ContentBlock) { + $options = []; + $label = $this->selectorLabel(); + $nestedOptions = Cp::cardPreviewOptions($field->getFieldLayout(), false); + foreach ($nestedOptions as $key => $option) { + $options[] = [ + 'label' => "$label - {$option['label']}", + 'value' => "contentBlock:{uid}/$key", + ]; + } + return $options; + } + + return parent::getPreviewOptions(); + } + /** * @inheritdoc */ diff --git a/src/helpers/Cp.php b/src/helpers/Cp.php index a3b6e55c30a..c76c4bfcd8b 100644 --- a/src/helpers/Cp.php +++ b/src/helpers/Cp.php @@ -37,6 +37,7 @@ use craft\events\RegisterCpAlertsEvent; use craft\fieldlayoutelements\BaseField; use craft\fieldlayoutelements\CustomField; +use craft\fields\ContentBlock; use craft\models\FieldLayout; use craft\models\FieldLayoutTab; use craft\models\Site; @@ -2766,30 +2767,7 @@ public static function cardViewDesignerHtml(FieldLayout $fieldLayout, array $con 'disabled' => false, ]; - $allOptions = $fieldLayout->type::cardAttributes($fieldLayout); - - foreach ($fieldLayout->getAllElements() as $layoutElement) { - if ($layoutElement instanceof BaseField && $layoutElement->previewable()) { - $allOptions["layoutElement:$layoutElement->uid"] = [ - 'label' => $layoutElement->label(), - ]; - } - } - - foreach ($fieldLayout->getGeneratedFields() as $field) { - if (($field['name'] ?? '') !== '') { - $allOptions["generatedField:{$field['uid']}"] = [ - 'label' => $field['name'], - ]; - } - } - - foreach ($allOptions as $key => &$option) { - if (!isset($option['value'])) { - $option['value'] = $key; - } - } - + $allOptions = self::cardPreviewOptions($fieldLayout); $selectedOptions = []; $remainingOptions = [...$allOptions]; @@ -2842,6 +2820,73 @@ public static function cardViewDesignerHtml(FieldLayout $fieldLayout, array $con Html::endTag('div'); // .card-view-designer } + /** + * Returns an array of available card preview options for the given field layout. + * + * @param FieldLayout $fieldLayout + * @return array{label:string,value:string}[] + * @since 5.9.0 + */ + public static function cardPreviewOptions(FieldLayout $fieldLayout, bool $withAttributes = true): array + { + return self::cardPreviewOptionsInternal($fieldLayout, '', '', $withAttributes); + } + + private static function cardPreviewOptionsInternal( + FieldLayout $fieldLayout, + string $keyPrefix, + string $labelPrefix, + bool $withAttributes, + ): array { + $allOptions = []; + + if ($withAttributes) { + foreach ($fieldLayout->type::cardAttributes($fieldLayout) as $key => $attribute) { + $allOptions[$keyPrefix . $key] = [ + 'label' => $labelPrefix . $attribute['label'], + 'placeholder' => $attribute['placeholder'], + ]; + } + } + + foreach ($fieldLayout->getAllElements() as $layoutElement) { + if ($layoutElement instanceof CustomField) { + $field = $layoutElement->getField(); + if ($field instanceof ContentBlock) { + $allOptions += self::cardPreviewOptionsInternal( + $field->getFieldLayout(), + "{$keyPrefix}contentBlock:$layoutElement->uid/", + sprintf('%s%s - ', $labelPrefix, $layoutElement->label()), + false, + ); + continue; + } + } + + if ($layoutElement instanceof BaseField && $layoutElement->previewable()) { + $allOptions["{$keyPrefix}layoutElement:$layoutElement->uid"] = [ + 'label' => sprintf('%s%s', $labelPrefix, $layoutElement->label()), + ]; + } + } + + foreach ($fieldLayout->getGeneratedFields() as $field) { + if (($field['name'] ?? '') !== '') { + $allOptions["generatedField:{$field['uid']}"] = [ + 'label' => $field['name'], + ]; + } + } + + foreach ($allOptions as $key => &$option) { + if (!isset($option['value'])) { + $option['value'] = $key; + } + } + + return $allOptions; + } + /** * Return HTML for managing thumbnail provider and position. * diff --git a/src/models/FieldLayout.php b/src/models/FieldLayout.php index 5600a3a0cf1..3387c83d53a 100644 --- a/src/models/FieldLayout.php +++ b/src/models/FieldLayout.php @@ -28,6 +28,7 @@ use craft\fieldlayoutelements\Markdown; use craft\fieldlayoutelements\Template; use craft\fieldlayoutelements\Tip; +use craft\fields\ContentBlock; use craft\helpers\ArrayHelper; use craft\helpers\Html; use craft\helpers\StringHelper; @@ -1085,11 +1086,7 @@ public function getCardBodyElements(?ElementInterface $element = null, array $ca $cardElements = []; foreach ($this->getCardView() as $key) { - $html = match (true) { - str_starts_with($key, 'layoutElement:') => $this->cardHtmlForLayoutElement($key, $element), - str_starts_with($key, 'generatedField:') => $this->cardHtmlForGeneratedField($key, $element), - default => $this->cardHtmlForAttribute($key, $element), - }; + $html = $this->getCardBodyHtmlForElement($key, $element); if ($html) { $cardElements[$key] = ['html' => $html]; @@ -1099,6 +1096,23 @@ public function getCardBodyElements(?ElementInterface $element = null, array $ca return $cardElements; } + /** + * Returns the card body HTML for a given card element key. + * + * @param string $key + * @param ElementInterface|null $element + * @since 5.9.0 + */ + public function getCardBodyHtmlForElement(string $key, ?ElementInterface $element = null): ?string + { + return match (true) { + str_starts_with($key, 'layoutElement:') => $this->cardHtmlForLayoutElement($key, $element), + str_starts_with($key, 'contentBlock:') => $this->cardHtmlForContentBlock($key, $element), + str_starts_with($key, 'generatedField:') => $this->cardHtmlForGeneratedField($key, $element), + default => $this->cardHtmlForAttribute($key, $element), + }; + } + private function cardHtmlForLayoutElement(string $key, ?ElementInterface $element): ?string { $uid = StringHelper::removeLeft($key, 'layoutElement:'); @@ -1124,6 +1138,36 @@ private function cardHtmlForLayoutElement(string $key, ?ElementInterface $elemen return $layoutElement->previewPlaceholderHtml(null, $element); } + private function cardHtmlForContentBlock(string $key, ?ElementInterface $element): ?string + { + // the key will be in the format `contentBlock:X::[...]::layoutElement:X` + $keyParts = explode('/', $key); + $key = array_shift($keyParts); + + // get the Content Block field + $uid = StringHelper::removeLeft($key, 'contentBlock:'); + $layoutElement = $this->getElementByUid($uid); + + if (!$layoutElement instanceof CustomField) { + return null; + } + + try { + $field = $layoutElement->getField(); + } catch (FieldNotFoundException) { + return null; + } + + if (!$field instanceof ContentBlock) { + return null; + } + + return $field->getFieldLayout()->getCardBodyHtmlForElement( + implode('/', $keyParts), + $element?->getFieldValue($field->handle), + ); + } + private function cardHtmlForGeneratedField(string $key, ?ElementInterface $element): ?string { $uid = StringHelper::removeLeft($key, 'generatedField:'); diff --git a/src/web/assets/cp/dist/cp.js b/src/web/assets/cp/dist/cp.js index 35c7bd3f045..e8bf631311b 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:E(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 T(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 E(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 L(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 k(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function A(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(L,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),k(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;k(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),k(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;k(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=$('