diff --git a/Build/Sources/TypeScript/backend/clipboard-panel.ts b/Build/Sources/TypeScript/backend/clipboard-panel.ts index bf2134300c4190c503388c650fe12484bcc1bba4..667961bee420288c343b4d85c532173a5134cd53 100644 --- a/Build/Sources/TypeScript/backend/clipboard-panel.ts +++ b/Build/Sources/TypeScript/backend/clipboard-panel.ts @@ -71,7 +71,7 @@ export class ClipboardPanel extends LitElement { return html` <div class="panel panel-default"> <div class="panel-loader"> - <typo3-backend-spinner size="small" variant="dark"></typo3-backend-spinner> + <typo3-backend-spinner size="small"></typo3-backend-spinner> </div> </div> `; diff --git a/Build/Sources/TypeScript/backend/element/spinner-element.ts b/Build/Sources/TypeScript/backend/element/spinner-element.ts index 726f12b0d9cc80254b81400a53b5e383442931f9..1e32493dd8519fe2075fb82b84c12c17e98ed524 100644 --- a/Build/Sources/TypeScript/backend/element/spinner-element.ts +++ b/Build/Sources/TypeScript/backend/element/spinner-element.ts @@ -11,45 +11,32 @@ * The TYPO3 project - inspiring people to share! */ -import { css, html, LitElement, TemplateResult } from 'lit'; +import { html, LitElement, TemplateResult } from 'lit'; import { customElement, property } from 'lit/decorators'; import { Sizes } from '../enum/icon-types'; import { IconStyles } from '@typo3/backend/icons'; -enum Variant { - light = 'light', - dark = 'dark' -} - /** * Module: @typo3/backend/element/spinner-element * * @example - * <typo3-backend-spinner size="small" variant="dark"></typo3-backend-spinner> + * <typo3-backend-spinner size="small"></typo3-backend-spinner> * + attribute size can be one of small, default, large or mega */ @customElement('typo3-backend-spinner') export class SpinnerElement extends LitElement { - public static styles = [ - ...IconStyles.getStyles(), - css` - :host([variant=dark]) svg { fill: #212121; } - :host([variant=light]) svg { fill: #fff; } - ` - ]; + static styles = IconStyles.getStyles(); @property({ type: String }) size: Sizes = Sizes.default; - @property({ type: String }) variant: Variant = Variant.dark; protected render(): TemplateResult { return html` <div class="icon-wrapper"> - <span class="icon icon-size-small icon-state-default icon-spin"> + <span class="icon icon-size-${this.size} icon-state-default icon-spin"> <span class="icon-markup"> <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 16 16"> - <g class="icon-color"> - <path d="M8 15c-3.86 0-7-3.141-7-7 0-3.86 3.14-7 7-7 3.859 0 7 3.14 7 7 0 3.859-3.141 7-7 7zM8 3C5.243 3 3 5.243 3 8s2.243 5 5 5 5-2.243 5-5-2.243-5-5-5z" opacity=".3"/> - <path d="M14 9a1 1 0 0 1-1-1c0-2.757-2.243-5-5-5a1 1 0 0 1 0-2c3.859 0 7 3.14 7 7a1 1 0 0 1-1 1z"/> + <g fill="currentColor"> + <path d="M8 15c-3.86 0-7-3.141-7-7 0-3.86 3.14-7 7-7 3.859 0 7 3.14 7 7 0 3.859-3.141 7-7 7zM8 3C5.243 3 3 5.243 3 8s2.243 5 5 5 5-2.243 5-5-2.243-5-5-5z" opacity=".3"/><path d="M14 9a1 1 0 0 1-1-1c0-2.757-2.243-5-5-5a1 1 0 0 1 0-2c3.859 0 7 3.14 7 7a1 1 0 0 1-1 1z"/> </g> </svg> </span> diff --git a/Build/Sources/TypeScript/backend/image-manipulation.ts b/Build/Sources/TypeScript/backend/image-manipulation.ts index e85cdea24bd5e34845d89df87248a9430d5032ed..06dc438da9d24732a2564cd330ee9b4ec2670836 100644 --- a/Build/Sources/TypeScript/backend/image-manipulation.ts +++ b/Build/Sources/TypeScript/backend/image-manipulation.ts @@ -232,7 +232,7 @@ class ImageManipulation { text: buttonSaveText, }, ], - content: html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`, + content: html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>`, size: Modal.sizes.full, style: Modal.styles.dark, title: modalTitle, diff --git a/Build/Sources/TypeScript/backend/modal.ts b/Build/Sources/TypeScript/backend/modal.ts index 95c2e410a673becda9466cb421cf78ce9744efb2..df4f3d8ebe057892a597d4fda2ec12f63ac5eaaf 100644 --- a/Build/Sources/TypeScript/backend/modal.ts +++ b/Build/Sources/TypeScript/backend/modal.ts @@ -217,7 +217,7 @@ export class ModalElement extends LitElement { this.templateResultContent = html`<p><strong>Oops, received a ${response.response.status} response from </strong> <span class="text-break">${this.content}</span>.</p>`; } }); - return html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`; + return html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>`; } return this.templateResultContent as TemplateResult; diff --git a/Build/Sources/TypeScript/backend/pagetsconfig/pagetsconfig-includes.ts b/Build/Sources/TypeScript/backend/pagetsconfig/pagetsconfig-includes.ts index 399289ce1089036106dc9934168196c75359d4d3..9c57c9b9956f8506beb817be4504c04e8fffc49e 100644 --- a/Build/Sources/TypeScript/backend/pagetsconfig/pagetsconfig-includes.ts +++ b/Build/Sources/TypeScript/backend/pagetsconfig/pagetsconfig-includes.ts @@ -43,7 +43,7 @@ class PageTsConfigIncludes { const size = Modal.sizes.large; const content = html`${until( this.fetchModalContent(url), - html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>` + html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>` )}`; Modal.advanced({ type, title, size, content }); }); diff --git a/Build/Sources/TypeScript/install/router.ts b/Build/Sources/TypeScript/install/router.ts index 9de568d03b7696b3e6bde06d0a76ae110bbc8ede..63d468ff31910550410332cca36bf52530d0555c 100644 --- a/Build/Sources/TypeScript/install/router.ts +++ b/Build/Sources/TypeScript/install/router.ts @@ -85,7 +85,7 @@ class Router { type: Modal.types.default, title: modalTitle, size: modalSize, - content: html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`, + content: html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>`, additionalCssClasses: ['install-tool-modal'], staticBackdrop: true, callback: (currentModal: ModalElement): void => { diff --git a/Build/Sources/TypeScript/tstemplate/template-analyzer.ts b/Build/Sources/TypeScript/tstemplate/template-analyzer.ts index 9ca647265811980b7dd006dcedefbb0ac0bed06d..53c1192fa264c2c1cd4200c4a26e5bb84a357c3f 100644 --- a/Build/Sources/TypeScript/tstemplate/template-analyzer.ts +++ b/Build/Sources/TypeScript/tstemplate/template-analyzer.ts @@ -43,7 +43,7 @@ class TemplateAnalyzer { const size = Modal.sizes.large; const content = html`${until( this.fetchModalContent(url), - html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>` + html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>` )}`; Modal.advanced({ type, title, size, content }); }); diff --git a/Build/Sources/TypeScript/workspaces/workspaces.ts b/Build/Sources/TypeScript/workspaces/workspaces.ts index 773f1bed0b7ae5ba8508b470d81e41e1271358f8..9baf0811c65e53b0d13a4dfb4582c31129b3b81a 100644 --- a/Build/Sources/TypeScript/workspaces/workspaces.ts +++ b/Build/Sources/TypeScript/workspaces/workspaces.ts @@ -31,7 +31,7 @@ export default class Workspaces { const modal = Modal.advanced({ title: TYPO3.lang.actionSendToStage, - content: html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`, + content: html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>`, severity: SeverityEnum.info, buttons: [ { diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/clipboard-panel.js b/typo3/sysext/backend/Resources/Public/JavaScript/clipboard-panel.js index 978ce041dcce0dff486481a548644484e54413a0..850819bae3a2a3f3a3dc12fe4cc49a2e58bc6746 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/clipboard-panel.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/clipboard-panel.js @@ -13,7 +13,7 @@ var ClipboardPanel_1,CopyMode,__decorate=function(t,e,o,a){var i,n=arguments.length,l=n<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,o):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(t,e,o,a);else for(var r=t.length-1;r>=0;r--)(i=t[r])&&(l=(n<3?i(l):n>3?i(e,o,l):i(e,o))||l);return n>3&&l&&Object.defineProperty(e,o,l),l};import{html,LitElement,nothing}from"lit";import{customElement,property}from"lit/decorators.js";import{until}from"lit/directives/until.js";import{unsafeHTML}from"lit/directives/unsafe-html.js";import{classMap}from"lit/directives/class-map.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import Notification from"@typo3/backend/notification.js";import"@typo3/backend/element/spinner-element.js";import"@typo3/backend/element/icon-element.js";!function(t){t.cut="cut",t.copy="copy"}(CopyMode||(CopyMode={}));let ClipboardPanel=ClipboardPanel_1=class extends LitElement{constructor(){super(...arguments),this.returnUrl="",this.table=""}static renderLoader(){return html` <div class="panel panel-default"> <div class="panel-loader"> - <typo3-backend-spinner size="small" variant="dark"></typo3-backend-spinner> + <typo3-backend-spinner size="small"></typo3-backend-spinner> </div> </div> `}createRenderRoot(){return this}render(){return html` diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/element/spinner-element.js b/typo3/sysext/backend/Resources/Public/JavaScript/element/spinner-element.js index 8e919f5e9f0f30c27e87a7a948b851caf22ac80f..67a9709faf4cf6e8ea3e04c1e3648de5f92fab46 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/element/spinner-element.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/element/spinner-element.js @@ -10,20 +10,16 @@ * * The TYPO3 project - inspiring people to share! */ -var Variant,__decorate=function(e,t,r,n){var i,o=arguments.length,s=o<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,n);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(o<3?i(s):o>3?i(t,r,s):i(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s};import{css,html,LitElement}from"lit";import{customElement,property}from"lit/decorators.js";import{Sizes}from"@typo3/backend/enum/icon-types.js";import{IconStyles}from"@typo3/backend/icons.js";!function(e){e.light="light",e.dark="dark"}(Variant||(Variant={}));let SpinnerElement=class extends LitElement{constructor(){super(...arguments),this.size=Sizes.default,this.variant=Variant.dark}render(){return html` +var __decorate=function(e,t,n,r){var o,s=arguments.length,i=s<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,n,r);else for(var c=e.length-1;c>=0;c--)(o=e[c])&&(i=(s<3?o(i):s>3?o(t,n,i):o(t,n))||i);return s>3&&i&&Object.defineProperty(t,n,i),i};import{html,LitElement}from"lit";import{customElement,property}from"lit/decorators.js";import{Sizes}from"@typo3/backend/enum/icon-types.js";import{IconStyles}from"@typo3/backend/icons.js";let SpinnerElement=class extends LitElement{constructor(){super(...arguments),this.size=Sizes.default}render(){return html` <div class="icon-wrapper"> - <span class="icon icon-size-small icon-state-default icon-spin"> + <span class="icon icon-size-${this.size} icon-state-default icon-spin"> <span class="icon-markup"> <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 16 16"> - <g class="icon-color"> - <path d="M8 15c-3.86 0-7-3.141-7-7 0-3.86 3.14-7 7-7 3.859 0 7 3.14 7 7 0 3.859-3.141 7-7 7zM8 3C5.243 3 3 5.243 3 8s2.243 5 5 5 5-2.243 5-5-2.243-5-5-5z" opacity=".3"/> - <path d="M14 9a1 1 0 0 1-1-1c0-2.757-2.243-5-5-5a1 1 0 0 1 0-2c3.859 0 7 3.14 7 7a1 1 0 0 1-1 1z"/> + <g fill="currentColor"> + <path d="M8 15c-3.86 0-7-3.141-7-7 0-3.86 3.14-7 7-7 3.859 0 7 3.14 7 7 0 3.859-3.141 7-7 7zM8 3C5.243 3 3 5.243 3 8s2.243 5 5 5 5-2.243 5-5-2.243-5-5-5z" opacity=".3"/><path d="M14 9a1 1 0 0 1-1-1c0-2.757-2.243-5-5-5a1 1 0 0 1 0-2c3.859 0 7 3.14 7 7a1 1 0 0 1-1 1z"/> </g> </svg> </span> </span> </div> - `}};SpinnerElement.styles=[...IconStyles.getStyles(),css` - :host([variant=dark]) svg { fill: #212121; } - :host([variant=light]) svg { fill: #fff; } - `],__decorate([property({type:String})],SpinnerElement.prototype,"size",void 0),__decorate([property({type:String})],SpinnerElement.prototype,"variant",void 0),SpinnerElement=__decorate([customElement("typo3-backend-spinner")],SpinnerElement);export{SpinnerElement}; \ No newline at end of file + `}};SpinnerElement.styles=IconStyles.getStyles(),__decorate([property({type:String})],SpinnerElement.prototype,"size",void 0),SpinnerElement=__decorate([customElement("typo3-backend-spinner")],SpinnerElement);export{SpinnerElement}; \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/image-manipulation.js b/typo3/sysext/backend/Resources/Public/JavaScript/image-manipulation.js index f1930e47d3159f6e31eb62cb2ae559f33497c3e4..9ff542dc936ab1878d724f722546a504e2fb0ab2 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/image-manipulation.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/image-manipulation.js @@ -10,7 +10,7 @@ * * The TYPO3 project - inspiring people to share! */ -import{html}from"lit";import{unsafeHTML}from"lit/directives/unsafe-html.js";import{styleMap}from"lit/directives/style-map.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import RegularEvent from"@typo3/core/event/regular-event.js";import FormEngineValidation from"@typo3/backend/form-engine-validation.js";import Cropper from"cropperjs";import{default as Modal}from"@typo3/backend/modal.js";import"@typo3/backend/element/spinner-element.js";import{renderNodes}from"@typo3/core/lit-helper.js";import{Offset}from"@typo3/backend/element/draggable-resizable-element.js";class ImageManipulation{constructor(){this.initialized=!1,this.triggerListener=null,this.cropImageSelector="#t3js-crop-image",this.coverAreaSelector=".t3js-cropper-cover-area",this.cropInfoSelector=".t3js-cropper-info-crop",this.focusAreaSelector="#t3js-cropper-focus-area",this.defaultFocusArea={height:1/3,width:1/3,x:0,y:0},this.defaultOpts={autoCrop:!0,autoCropArea:.7,dragMode:"crop",guides:!0,responsive:!0,viewMode:1,zoomable:!1,checkCrossOrigin:!1},this.cropBuiltHandler=()=>{this.initialized=!0;const t=this.cropper.getImageData(),e=this.currentModal.querySelector(this.cropImageSelector);this.currentModal.querySelector(".cropper-canvas img")?.classList.remove("cropper-hide"),this.imageOriginalSizeFactor=parseInt(e.dataset.originalWidth,10)/t.naturalWidth,this.cropVariantTriggers.forEach((e=>{const r=e.dataset.cropVariantId,a=this.convertRelativeToAbsoluteCropArea(this.data[r].cropArea,t),i=Object.assign({},this.data[r],{cropArea:a});this.updatePreviewThumbnail(i,e)})),this.currentCropVariant.cropArea=this.convertRelativeToAbsoluteCropArea(this.currentCropVariant.cropArea,t),this.cropBox=this.currentModal.querySelector(".cropper-crop-box"),this.setCropArea(this.currentCropVariant.cropArea),this.currentCropVariant.coverAreas&&this.initCoverAreas(this.cropBox,this.currentCropVariant.coverAreas),this.currentCropVariant.focusArea&&(ImageManipulation.isEmptyObject(this.currentCropVariant.focusArea)&&(this.currentCropVariant.focusArea=Object.assign({},this.defaultFocusArea)),this.focusAreaEl?.remove(),this.initFocusArea(this.cropBox)),this.currentCropVariant.selectedRatio&&this.currentModal.querySelector(`[data-bs-option='${this.currentCropVariant.selectedRatio}']`)?.classList.add("active")},this.cropMoveHandler=t=>{if(!this.initialized)return;let e=Math.ceil(t.detail.width),r=Math.ceil(t.detail.height);(e<15||r<15)&&(e=Math.max(15,r),r=Math.max(15,e),this.cropper.setData({width:e,height:r})),this.currentCropVariant.cropArea=Object.assign({},this.currentCropVariant.cropArea,{width:Math.floor(e),height:Math.floor(r),x:Math.floor(t.detail.x),y:Math.floor(t.detail.y)}),this.focusAreaEl&&this.currentCropVariant?.focusArea&&(this.focusAreaEl.offset=this.convertAreaToOffset(this.currentCropVariant.focusArea,this.cropBox)),this.updatePreviewThumbnail(this.currentCropVariant,this.activeCropVariantTrigger),this.updateCropVariantData(this.currentCropVariant);const a=Math.round(this.currentCropVariant.cropArea.width*this.imageOriginalSizeFactor),i=Math.round(this.currentCropVariant.cropArea.height*this.imageOriginalSizeFactor);this.cropInfo.innerText=`${a}×${i} px`}}static wait(t,e){window.setTimeout(t,e)}static toCssPercent(t){return 100*t+"%"}static serializeCropVariants(t){return JSON.stringify(t,((t,e)=>"id"===t||"title"===t||"allowedAspectRatios"===t||"coverAreas"===t?void 0:e))}static isEmptyObject(t){return!t||"object"!=typeof t||0===Object.keys(t).length||"{}"===JSON.stringify(t)}static resolvePointerEventNames(){const t="undefined"!=typeof window&&void 0!==window.document,e=!(!t||!window.document.documentElement)&&"ontouchstart"in window.document.documentElement,r=!!t&&"PointerEvent"in window,a=e?["touchmove"]:["mousemove"],i=e?["touchstart"]:["mousedown"],o=e?["touchend","touchcancel"]:["mouseup"];return{touchStart:i,touchMove:a,touchEnd:o,pointerDown:r?["pointerdown"]:i,pointerMove:r?["pointermove"]:a,pointerUp:r?["pointerup","pointercancel"]:o}}initializeTrigger(){this.triggerListener||(this.triggerListener=new RegularEvent("click",((t,e)=>{t.preventDefault(),this.trigger=e,this.show()})),this.triggerListener.delegateTo(document,".t3js-image-manipulation-trigger"))}async initializeCropperModal(){const t=this.currentModal.querySelector(this.cropImageSelector);await new Promise((e=>{t.complete?e():t.addEventListener("load",(()=>e()))})),this.init()}show(){const t=this.trigger.dataset,e=t.modalTitle,r=t.buttonPreviewText,a=t.buttonDismissText,i=t.buttonSaveText,o=t.url,s=JSON.parse(t.payload);this.currentModal=Modal.advanced({additionalCssClasses:["modal-image-manipulation","cropper"],buttons:[{btnClass:"btn-default float-start",name:"preview",icon:"actions-view",text:r},{btnClass:"btn-default",name:"dismiss",icon:"actions-close",text:a},{btnClass:"btn-primary",name:"save",icon:"actions-document-save",text:i}],content:html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`,size:Modal.sizes.full,style:Modal.styles.dark,title:e,staticBackdrop:!0}),this.currentModal.addEventListener("typo3-modal-shown",(()=>{new AjaxRequest(o).post(s).then((async t=>{const e=await t.resolve();this.currentModal.templateResultContent=html`${unsafeHTML(e)}`,this.currentModal.updateComplete.then((()=>this.initializeCropperModal()))}))})),this.currentModal.addEventListener("typo3-modal-hide",(()=>{this.destroy()}))}init(){const t=this.currentModal.querySelector(this.cropImageSelector),e=this.trigger.dataset.cropVariants;if(!e)throw new TypeError("ImageManipulation: No cropVariants data found for image");this.data=ImageManipulation.isEmptyObject(this.data)?JSON.parse(e):this.data,this.cropVariantTriggers=this.currentModal.querySelectorAll(".t3js-crop-variant-trigger"),this.activeCropVariantTrigger=this.currentModal.querySelector(".t3js-crop-variant-trigger.is-active"),this.cropInfo=this.currentModal.querySelector(this.cropInfoSelector),this.currentCropVariant=this.data[this.activeCropVariantTrigger.dataset.cropVariantId],this.cropVariantTriggers.forEach((t=>t.addEventListener("click",(t=>{if(t.currentTarget.classList.contains("is-active"))return t.stopPropagation(),void t.preventDefault();this.activeCropVariantTrigger.classList.remove("is-active"),t.currentTarget.classList.add("is-active"),this.activeCropVariantTrigger=t.currentTarget;const e=this.data[this.activeCropVariantTrigger.dataset.cropVariantId],r=this.cropper.getImageData();e.cropArea=this.convertRelativeToAbsoluteCropArea(e.cropArea,r),this.currentCropVariant=Object.assign({},e),this.update(e)})))),new RegularEvent("click",((t,e)=>{const r=e.dataset.bsOption,a=Object.assign({},this.currentCropVariant),i=a.allowedAspectRatios[r];this.setAspectRatio(i),this.setCropArea(a.cropArea),this.currentCropVariant=Object.assign({},a,{selectedRatio:r}),this.update(this.currentCropVariant)})).delegateTo(this.currentModal,"label[data-method=setAspectRatio]"),new RegularEvent("click",(()=>this.save(this.data))).delegateTo(this.currentModal,"button[name=save]"),this.trigger.dataset.previewUrl?new RegularEvent("click",(()=>this.openPreview(this.data))).delegateTo(this.currentModal,"button[name=preview]"):this.currentModal.querySelectorAll("button[name=preview]").forEach((t=>t.style.display="none")),new RegularEvent("click",(()=>this.currentModal.hideModal())).delegateTo(this.currentModal,"button[name=dismiss]"),new RegularEvent("click",((t,e)=>{const r=this.cropper.getImageData(),a=e.dataset.cropVariant;if(t.preventDefault(),t.stopPropagation(),!a)throw new TypeError("TYPO3 Cropper: No cropVariant data attribute found on reset element.");const i=JSON.parse(a),o=this.convertRelativeToAbsoluteCropArea(i.cropArea,r);this.currentCropVariant=Object.assign({},i,{cropArea:o}),this.update(this.currentCropVariant)})).delegateTo(this.currentModal,"button[name=reset]"),ImageManipulation.isEmptyObject(this.currentCropVariant.cropArea)&&(this.defaultOpts=Object.assign({autoCropArea:1},this.defaultOpts)),this.cropper=new Cropper(t,Object.assign({},this.defaultOpts,{ready:()=>{this.cropBuiltHandler(),this.update(this.currentCropVariant)},crop:this.cropMoveHandler.bind(this),data:this.currentCropVariant.cropArea}))}update(t){const e=Object.assign({},t),r=t.allowedAspectRatios[t.selectedRatio];this.currentModal.querySelector("[data-bs-option].active")?.classList.remove("active"),this.currentModal.querySelector(`[data-bs-option="${t.selectedRatio}"]`)?.classList.add("active"),this.setAspectRatio(r),this.setCropArea(e.cropArea),this.currentCropVariant=Object.assign({},e,t),this.cropBox?.querySelector(this.coverAreaSelector)?.remove(),this.cropBox?.querySelectorAll(this.focusAreaSelector)?.length>0&&this.focusAreaEl.remove(),t.focusArea&&(ImageManipulation.isEmptyObject(t.focusArea)&&(this.currentCropVariant.focusArea=Object.assign({},this.defaultFocusArea)),this.focusAreaEl?.remove(),this.initFocusArea(this.cropBox)),t.coverAreas&&this.initCoverAreas(this.cropBox,this.currentCropVariant.coverAreas),this.updatePreviewThumbnail(this.currentCropVariant,this.activeCropVariantTrigger)}initFocusArea(t){this.focusAreaEl=document.createElement("typo3-backend-draggable-resizable"),this.focusAreaEl.window=this.currentModal.ownerDocument.defaultView,this.focusAreaEl.offset=this.convertAreaToOffset(this.currentCropVariant.focusArea,t),this.focusAreaEl.container=t,this.focusAreaEl.pointerEventNames=ImageManipulation.resolvePointerEventNames(),this.focusAreaEl.addEventListener("draggable-resizable-started",(()=>{this.cropper.disable()})),this.focusAreaEl.addEventListener("draggable-resizable-updated",(()=>{const e=this.currentCropVariant.coverAreas,r=this.convertOffsetToArea(this.focusAreaEl.offset,t),a=this.focusAreaEl.querySelector(this.focusAreaSelector);this.checkFocusAndCoverAreasCollision(r,e)?a.classList.add("has-nodrop"):a.classList.remove("has-nodrop")})),this.focusAreaEl.addEventListener("draggable-resizable-finished",(e=>{const r=this.currentCropVariant.coverAreas,a=this.convertOffsetToArea(this.focusAreaEl.offset,t);this.checkFocusAndCoverAreasCollision(a,r)?this.focusAreaEl.revert(e.detail.originOffset):this.scaleAndMoveFocusArea(a);this.focusAreaEl.querySelector(this.focusAreaSelector).classList.remove("has-nodrop"),this.cropper.enable()})),t.appendChild(this.focusAreaEl),this.scaleAndMoveFocusArea(this.currentCropVariant.focusArea)}initCoverAreas(t,e){e.forEach((e=>{const r={height:ImageManipulation.toCssPercent(e.height),left:ImageManipulation.toCssPercent(e.x),top:ImageManipulation.toCssPercent(e.y),width:ImageManipulation.toCssPercent(e.width)},a=html` +import{html}from"lit";import{unsafeHTML}from"lit/directives/unsafe-html.js";import{styleMap}from"lit/directives/style-map.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import RegularEvent from"@typo3/core/event/regular-event.js";import FormEngineValidation from"@typo3/backend/form-engine-validation.js";import Cropper from"cropperjs";import{default as Modal}from"@typo3/backend/modal.js";import"@typo3/backend/element/spinner-element.js";import{renderNodes}from"@typo3/core/lit-helper.js";import{Offset}from"@typo3/backend/element/draggable-resizable-element.js";class ImageManipulation{constructor(){this.initialized=!1,this.triggerListener=null,this.cropImageSelector="#t3js-crop-image",this.coverAreaSelector=".t3js-cropper-cover-area",this.cropInfoSelector=".t3js-cropper-info-crop",this.focusAreaSelector="#t3js-cropper-focus-area",this.defaultFocusArea={height:1/3,width:1/3,x:0,y:0},this.defaultOpts={autoCrop:!0,autoCropArea:.7,dragMode:"crop",guides:!0,responsive:!0,viewMode:1,zoomable:!1,checkCrossOrigin:!1},this.cropBuiltHandler=()=>{this.initialized=!0;const t=this.cropper.getImageData(),e=this.currentModal.querySelector(this.cropImageSelector);this.currentModal.querySelector(".cropper-canvas img")?.classList.remove("cropper-hide"),this.imageOriginalSizeFactor=parseInt(e.dataset.originalWidth,10)/t.naturalWidth,this.cropVariantTriggers.forEach((e=>{const r=e.dataset.cropVariantId,a=this.convertRelativeToAbsoluteCropArea(this.data[r].cropArea,t),i=Object.assign({},this.data[r],{cropArea:a});this.updatePreviewThumbnail(i,e)})),this.currentCropVariant.cropArea=this.convertRelativeToAbsoluteCropArea(this.currentCropVariant.cropArea,t),this.cropBox=this.currentModal.querySelector(".cropper-crop-box"),this.setCropArea(this.currentCropVariant.cropArea),this.currentCropVariant.coverAreas&&this.initCoverAreas(this.cropBox,this.currentCropVariant.coverAreas),this.currentCropVariant.focusArea&&(ImageManipulation.isEmptyObject(this.currentCropVariant.focusArea)&&(this.currentCropVariant.focusArea=Object.assign({},this.defaultFocusArea)),this.focusAreaEl?.remove(),this.initFocusArea(this.cropBox)),this.currentCropVariant.selectedRatio&&this.currentModal.querySelector(`[data-bs-option='${this.currentCropVariant.selectedRatio}']`)?.classList.add("active")},this.cropMoveHandler=t=>{if(!this.initialized)return;let e=Math.ceil(t.detail.width),r=Math.ceil(t.detail.height);(e<15||r<15)&&(e=Math.max(15,r),r=Math.max(15,e),this.cropper.setData({width:e,height:r})),this.currentCropVariant.cropArea=Object.assign({},this.currentCropVariant.cropArea,{width:Math.floor(e),height:Math.floor(r),x:Math.floor(t.detail.x),y:Math.floor(t.detail.y)}),this.focusAreaEl&&this.currentCropVariant?.focusArea&&(this.focusAreaEl.offset=this.convertAreaToOffset(this.currentCropVariant.focusArea,this.cropBox)),this.updatePreviewThumbnail(this.currentCropVariant,this.activeCropVariantTrigger),this.updateCropVariantData(this.currentCropVariant);const a=Math.round(this.currentCropVariant.cropArea.width*this.imageOriginalSizeFactor),i=Math.round(this.currentCropVariant.cropArea.height*this.imageOriginalSizeFactor);this.cropInfo.innerText=`${a}×${i} px`}}static wait(t,e){window.setTimeout(t,e)}static toCssPercent(t){return 100*t+"%"}static serializeCropVariants(t){return JSON.stringify(t,((t,e)=>"id"===t||"title"===t||"allowedAspectRatios"===t||"coverAreas"===t?void 0:e))}static isEmptyObject(t){return!t||"object"!=typeof t||0===Object.keys(t).length||"{}"===JSON.stringify(t)}static resolvePointerEventNames(){const t="undefined"!=typeof window&&void 0!==window.document,e=!(!t||!window.document.documentElement)&&"ontouchstart"in window.document.documentElement,r=!!t&&"PointerEvent"in window,a=e?["touchmove"]:["mousemove"],i=e?["touchstart"]:["mousedown"],o=e?["touchend","touchcancel"]:["mouseup"];return{touchStart:i,touchMove:a,touchEnd:o,pointerDown:r?["pointerdown"]:i,pointerMove:r?["pointermove"]:a,pointerUp:r?["pointerup","pointercancel"]:o}}initializeTrigger(){this.triggerListener||(this.triggerListener=new RegularEvent("click",((t,e)=>{t.preventDefault(),this.trigger=e,this.show()})),this.triggerListener.delegateTo(document,".t3js-image-manipulation-trigger"))}async initializeCropperModal(){const t=this.currentModal.querySelector(this.cropImageSelector);await new Promise((e=>{t.complete?e():t.addEventListener("load",(()=>e()))})),this.init()}show(){const t=this.trigger.dataset,e=t.modalTitle,r=t.buttonPreviewText,a=t.buttonDismissText,i=t.buttonSaveText,o=t.url,s=JSON.parse(t.payload);this.currentModal=Modal.advanced({additionalCssClasses:["modal-image-manipulation","cropper"],buttons:[{btnClass:"btn-default float-start",name:"preview",icon:"actions-view",text:r},{btnClass:"btn-default",name:"dismiss",icon:"actions-close",text:a},{btnClass:"btn-primary",name:"save",icon:"actions-document-save",text:i}],content:html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>`,size:Modal.sizes.full,style:Modal.styles.dark,title:e,staticBackdrop:!0}),this.currentModal.addEventListener("typo3-modal-shown",(()=>{new AjaxRequest(o).post(s).then((async t=>{const e=await t.resolve();this.currentModal.templateResultContent=html`${unsafeHTML(e)}`,this.currentModal.updateComplete.then((()=>this.initializeCropperModal()))}))})),this.currentModal.addEventListener("typo3-modal-hide",(()=>{this.destroy()}))}init(){const t=this.currentModal.querySelector(this.cropImageSelector),e=this.trigger.dataset.cropVariants;if(!e)throw new TypeError("ImageManipulation: No cropVariants data found for image");this.data=ImageManipulation.isEmptyObject(this.data)?JSON.parse(e):this.data,this.cropVariantTriggers=this.currentModal.querySelectorAll(".t3js-crop-variant-trigger"),this.activeCropVariantTrigger=this.currentModal.querySelector(".t3js-crop-variant-trigger.is-active"),this.cropInfo=this.currentModal.querySelector(this.cropInfoSelector),this.currentCropVariant=this.data[this.activeCropVariantTrigger.dataset.cropVariantId],this.cropVariantTriggers.forEach((t=>t.addEventListener("click",(t=>{if(t.currentTarget.classList.contains("is-active"))return t.stopPropagation(),void t.preventDefault();this.activeCropVariantTrigger.classList.remove("is-active"),t.currentTarget.classList.add("is-active"),this.activeCropVariantTrigger=t.currentTarget;const e=this.data[this.activeCropVariantTrigger.dataset.cropVariantId],r=this.cropper.getImageData();e.cropArea=this.convertRelativeToAbsoluteCropArea(e.cropArea,r),this.currentCropVariant=Object.assign({},e),this.update(e)})))),new RegularEvent("click",((t,e)=>{const r=e.dataset.bsOption,a=Object.assign({},this.currentCropVariant),i=a.allowedAspectRatios[r];this.setAspectRatio(i),this.setCropArea(a.cropArea),this.currentCropVariant=Object.assign({},a,{selectedRatio:r}),this.update(this.currentCropVariant)})).delegateTo(this.currentModal,"label[data-method=setAspectRatio]"),new RegularEvent("click",(()=>this.save(this.data))).delegateTo(this.currentModal,"button[name=save]"),this.trigger.dataset.previewUrl?new RegularEvent("click",(()=>this.openPreview(this.data))).delegateTo(this.currentModal,"button[name=preview]"):this.currentModal.querySelectorAll("button[name=preview]").forEach((t=>t.style.display="none")),new RegularEvent("click",(()=>this.currentModal.hideModal())).delegateTo(this.currentModal,"button[name=dismiss]"),new RegularEvent("click",((t,e)=>{const r=this.cropper.getImageData(),a=e.dataset.cropVariant;if(t.preventDefault(),t.stopPropagation(),!a)throw new TypeError("TYPO3 Cropper: No cropVariant data attribute found on reset element.");const i=JSON.parse(a),o=this.convertRelativeToAbsoluteCropArea(i.cropArea,r);this.currentCropVariant=Object.assign({},i,{cropArea:o}),this.update(this.currentCropVariant)})).delegateTo(this.currentModal,"button[name=reset]"),ImageManipulation.isEmptyObject(this.currentCropVariant.cropArea)&&(this.defaultOpts=Object.assign({autoCropArea:1},this.defaultOpts)),this.cropper=new Cropper(t,Object.assign({},this.defaultOpts,{ready:()=>{this.cropBuiltHandler(),this.update(this.currentCropVariant)},crop:this.cropMoveHandler.bind(this),data:this.currentCropVariant.cropArea}))}update(t){const e=Object.assign({},t),r=t.allowedAspectRatios[t.selectedRatio];this.currentModal.querySelector("[data-bs-option].active")?.classList.remove("active"),this.currentModal.querySelector(`[data-bs-option="${t.selectedRatio}"]`)?.classList.add("active"),this.setAspectRatio(r),this.setCropArea(e.cropArea),this.currentCropVariant=Object.assign({},e,t),this.cropBox?.querySelector(this.coverAreaSelector)?.remove(),this.cropBox?.querySelectorAll(this.focusAreaSelector)?.length>0&&this.focusAreaEl.remove(),t.focusArea&&(ImageManipulation.isEmptyObject(t.focusArea)&&(this.currentCropVariant.focusArea=Object.assign({},this.defaultFocusArea)),this.focusAreaEl?.remove(),this.initFocusArea(this.cropBox)),t.coverAreas&&this.initCoverAreas(this.cropBox,this.currentCropVariant.coverAreas),this.updatePreviewThumbnail(this.currentCropVariant,this.activeCropVariantTrigger)}initFocusArea(t){this.focusAreaEl=document.createElement("typo3-backend-draggable-resizable"),this.focusAreaEl.window=this.currentModal.ownerDocument.defaultView,this.focusAreaEl.offset=this.convertAreaToOffset(this.currentCropVariant.focusArea,t),this.focusAreaEl.container=t,this.focusAreaEl.pointerEventNames=ImageManipulation.resolvePointerEventNames(),this.focusAreaEl.addEventListener("draggable-resizable-started",(()=>{this.cropper.disable()})),this.focusAreaEl.addEventListener("draggable-resizable-updated",(()=>{const e=this.currentCropVariant.coverAreas,r=this.convertOffsetToArea(this.focusAreaEl.offset,t),a=this.focusAreaEl.querySelector(this.focusAreaSelector);this.checkFocusAndCoverAreasCollision(r,e)?a.classList.add("has-nodrop"):a.classList.remove("has-nodrop")})),this.focusAreaEl.addEventListener("draggable-resizable-finished",(e=>{const r=this.currentCropVariant.coverAreas,a=this.convertOffsetToArea(this.focusAreaEl.offset,t);this.checkFocusAndCoverAreasCollision(a,r)?this.focusAreaEl.revert(e.detail.originOffset):this.scaleAndMoveFocusArea(a);this.focusAreaEl.querySelector(this.focusAreaSelector).classList.remove("has-nodrop"),this.cropper.enable()})),t.appendChild(this.focusAreaEl),this.scaleAndMoveFocusArea(this.currentCropVariant.focusArea)}initCoverAreas(t,e){e.forEach((e=>{const r={height:ImageManipulation.toCssPercent(e.height),left:ImageManipulation.toCssPercent(e.x),top:ImageManipulation.toCssPercent(e.y),width:ImageManipulation.toCssPercent(e.width)},a=html` <div class="cropper-cover-area t3js-cropper-cover-area" style=${styleMap(r)}></div> `;this.renderElements(a,t)}))}updatePreviewThumbnail(t,e){const r=e.querySelector(".t3js-cropper-preview-thumbnail-crop-area"),a=e.querySelector(".t3js-cropper-preview-thumbnail-crop-image"),i=e.querySelector(".t3js-cropper-preview-thumbnail-focus-area"),o=this.cropper.getImageData();Object.assign(r.style,{height:ImageManipulation.toCssPercent(t.cropArea.height/o.naturalHeight),left:ImageManipulation.toCssPercent(t.cropArea.x/o.naturalWidth),top:ImageManipulation.toCssPercent(t.cropArea.y/o.naturalHeight),width:ImageManipulation.toCssPercent(t.cropArea.width/o.naturalWidth)}),t.focusArea&&Object.assign(i.style,{height:ImageManipulation.toCssPercent(t.focusArea.height),left:ImageManipulation.toCssPercent(t.focusArea.x),top:ImageManipulation.toCssPercent(t.focusArea.y),width:ImageManipulation.toCssPercent(t.focusArea.width)});const s=getComputedStyle(r),n={width:s.getPropertyValue("width"),height:s.getPropertyValue("height"),left:s.getPropertyValue("left"),top:s.getPropertyValue("top")};Object.assign(a.style,{height:parseFloat(n.height)*(1/(t.cropArea.height/o.naturalHeight))+"px",margin:-1*parseFloat(n.left)+"px",marginTop:-1*parseFloat(n.top)+"px",width:parseFloat(n.width)*(1/(t.cropArea.width/o.naturalWidth))+"px"})}scaleAndMoveFocusArea(t){this.currentCropVariant.focusArea=t,this.updatePreviewThumbnail(this.currentCropVariant,this.activeCropVariantTrigger),this.updateCropVariantData(this.currentCropVariant)}updateCropVariantData(t){const e=this.cropper.getImageData(),r=this.convertAbsoluteToRelativeCropArea(t.cropArea,e);this.data[t.id]=Object.assign({},t,{cropArea:r})}setAspectRatio(t){this.cropper.setAspectRatio(t.value)}setCropArea(t){const e=this.currentCropVariant.allowedAspectRatios[this.currentCropVariant.selectedRatio];0===e.value?this.cropper.setData({height:t.height,width:t.width,x:t.x,y:t.y}):this.cropper.setData({height:t.height,width:t.height*e.value,x:t.x,y:t.y})}checkFocusAndCoverAreasCollision(t,e){return!!e&&e.some((e=>t.x<e.x+e.width&&e.x<t.x+t.width&&t.y<e.y+e.height&&e.y<t.height+t.y))}convertAbsoluteToRelativeCropArea(t,e){const{height:r,width:a,x:i,y:o}=t;return{height:r/e.naturalHeight,width:a/e.naturalWidth,x:i/e.naturalWidth,y:o/e.naturalHeight}}convertRelativeToAbsoluteCropArea(t,e){const{height:r,width:a,x:i,y:o}=t;return{height:r*e.naturalHeight,width:a*e.naturalWidth,x:i*e.naturalWidth,y:o*e.naturalHeight}}setPreviewImages(t){const e=this.cropper.image,r=this.cropper.getImageData();Object.keys(t).forEach((a=>{const i=t[a],o=this.convertRelativeToAbsoluteCropArea(i.cropArea,r),s=this.trigger.closest(".form-group").querySelector(`.t3js-image-manipulation-preview[data-crop-variant-id="${a}"]`),n=this.trigger.closest(".form-group").querySelector(`.t3js-image-manipulation-selected-ratio[data-crop-variant-id="${a}"]`);if(!(s instanceof HTMLElement))return;let c=s.getBoundingClientRect().width,h=parseInt(s.dataset.previewHeight,10);const l=o.width/o.height,p=c/l;p>h?c=h*l:h=p,c>o.width&&(c=o.width,h=o.height);const u=c/o.width,d={height:r.naturalHeight*u+"px",left:-o.x*u+"px",top:-o.y*u+"px",width:r.naturalWidth*u+"px"},g=html` <span class="thumbnail thumbnail-status"> diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/modal.js b/typo3/sysext/backend/Resources/Public/JavaScript/modal.js index 0175e47128379c32ae91e893e2d9a9869d37382c..b3dcbb46916360d106f151e42ae9731f00416449 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/modal.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/modal.js @@ -41,7 +41,7 @@ var Identifiers,__decorate=function(t,e,a,o){var s,n=arguments.length,i=n<3?e:nu </div> </div> </div> - `}_buttonClick(t,e){const a=t.currentTarget;e.action?(this.activeButton=e,e.action.execute(a).then((()=>this.bootstrapModal.hide()))):e.trigger&&e.trigger(t,this),a.dispatchEvent(new CustomEvent("button.clicked",{bubbles:!0}))}renderAjaxBody(){return null===this.templateResultContent?(new AjaxRequest(this.content).get().then((async t=>{const e=await t.raw().text();this.templateResultContent=html`${unsafeHTML(e)}`,this.updateComplete.then((()=>{this.ajaxCallback&&this.ajaxCallback(this),this.dispatchEvent(new CustomEvent("modal-loaded"))}))})).catch((async t=>{const e=await t.raw().text();this.templateResultContent=e?html`${unsafeHTML(e)}`:html`<p><strong>Oops, received a ${t.response.status} response from </strong> <span class="text-break">${this.content}</span>.</p>`})),html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`):this.templateResultContent}renderModalBody(){if(this.type===Types.ajax)return this.renderAjaxBody();if(this.type===Types.iframe){const t=t=>{const e=t.currentTarget;this.modalTitle=e.contentDocument.title,e.contentDocument.body.classList.add("with-overflow")};return html` + `}_buttonClick(t,e){const a=t.currentTarget;e.action?(this.activeButton=e,e.action.execute(a).then((()=>this.bootstrapModal.hide()))):e.trigger&&e.trigger(t,this),a.dispatchEvent(new CustomEvent("button.clicked",{bubbles:!0}))}renderAjaxBody(){return null===this.templateResultContent?(new AjaxRequest(this.content).get().then((async t=>{const e=await t.raw().text();this.templateResultContent=html`${unsafeHTML(e)}`,this.updateComplete.then((()=>{this.ajaxCallback&&this.ajaxCallback(this),this.dispatchEvent(new CustomEvent("modal-loaded"))}))})).catch((async t=>{const e=await t.raw().text();this.templateResultContent=e?html`${unsafeHTML(e)}`:html`<p><strong>Oops, received a ${t.response.status} response from </strong> <span class="text-break">${this.content}</span>.</p>`})),html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>`):this.templateResultContent}renderModalBody(){if(this.type===Types.ajax)return this.renderAjaxBody();if(this.type===Types.iframe){const t=t=>{const e=t.currentTarget;this.modalTitle=e.contentDocument.title,e.contentDocument.body.classList.add("with-overflow")};return html` <iframe src="${this.content}" name="modal_frame" class="modal-iframe t3js-modal-iframe" @load=${t}></iframe> `}return this.type===Types.template?this.templateResultContent:html`<p>${this.content}</p>`}renderModalButton(t){const e={btn:!0,[t.btnClass||"btn-default"]:!0,"t3js-active":t.active,disabled:this.activeButton&&this.activeButton!==t};return html` <button class=${classMap(e)} diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/pagetsconfig/pagetsconfig-includes.js b/typo3/sysext/backend/Resources/Public/JavaScript/pagetsconfig/pagetsconfig-includes.js index 9cf60d62e199eaa781c3850bbfd2cee5cd167eae..876494ee8707079ed36f026b8fd36be6a66b8268 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/pagetsconfig/pagetsconfig-includes.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/pagetsconfig/pagetsconfig-includes.js @@ -10,7 +10,7 @@ * * The TYPO3 project - inspiring people to share! */ -import DocumentService from"@typo3/core/document-service.js";import{default as Modal}from"@typo3/backend/modal.js";import{topLevelModuleImport}from"@typo3/backend/utility/top-level-module-import.js";import{html}from"lit";import{until}from"lit/directives/until.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";class PageTsConfigIncludes{constructor(){this.registerEventListeners()}async registerEventListeners(){await DocumentService.ready(),document.querySelectorAll(".t3js-pagetsconfig-includes-modal").forEach((e=>{e.addEventListener("click",(t=>{t.preventDefault();const o=Modal.types.default,r=e.dataset.modalTitle||e.textContent.trim(),a=e.getAttribute("href"),l=Modal.sizes.large,i=html`${until(this.fetchModalContent(a),html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`)}`;Modal.advanced({type:o,title:r,size:l,content:i})}))}))}async fetchModalContent(e){topLevelModuleImport("@typo3/backend/code-editor/element/code-mirror-element.js");const t=await new AjaxRequest(e).get(),o=await t.resolve();return html` +import DocumentService from"@typo3/core/document-service.js";import{default as Modal}from"@typo3/backend/modal.js";import{topLevelModuleImport}from"@typo3/backend/utility/top-level-module-import.js";import{html}from"lit";import{until}from"lit/directives/until.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";class PageTsConfigIncludes{constructor(){this.registerEventListeners()}async registerEventListeners(){await DocumentService.ready(),document.querySelectorAll(".t3js-pagetsconfig-includes-modal").forEach((e=>{e.addEventListener("click",(t=>{t.preventDefault();const o=Modal.types.default,r=e.dataset.modalTitle||e.textContent.trim(),a=e.getAttribute("href"),l=Modal.sizes.large,i=html`${until(this.fetchModalContent(a),html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>`)}`;Modal.advanced({type:o,title:r,size:l,content:i})}))}))}async fetchModalContent(e){topLevelModuleImport("@typo3/backend/code-editor/element/code-mirror-element.js");const t=await new AjaxRequest(e).get(),o=await t.resolve();return html` <typo3-t3editor-codemirror .mode="${{name:"@typo3/backend/code-editor/language/typoscript.js",flags:2,exportName:"typoscript",items:[{type:"invoke",args:[]}]}}" nolazyload readonly class="flex-grow-1 mh-100"> <textarea readonly disabled class="form-control">${o}</textarea> </typo3-t3editor-codemirror> diff --git a/typo3/sysext/install/Resources/Public/JavaScript/router.js b/typo3/sysext/install/Resources/Public/JavaScript/router.js index ea886a83cc792f21bf25830345330f773cf68be9..d64ab8a178c2cce7eff2f869d0dd189c98c058cf 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/router.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/router.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -import{html}from"lit";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import{default as Modal}from"@typo3/backend/modal.js";import{InfoBox}from"@typo3/install/renderable/info-box.js";import"@typo3/install/renderable/progress-bar.js";import Severity from"@typo3/install/renderable/severity.js";import"@typo3/backend/element/spinner-element.js";import RegularEvent from"@typo3/core/event/regular-event.js";class Router{constructor(){this.rootSelector=".t3js-body",this.contentSelector=".t3js-module-body",this.scaffoldSelector=".t3js-scaffold",this.scaffoldContentOverlaySelector=".t3js-scaffold-content-overlay",this.scaffoldMenuToggleSelector=".t3js-topbar-button-modulemenu"}setContent(e){const t=this.rootContainer.querySelector(this.contentSelector);"string"==typeof e&&(e=document.createRange().createContextualFragment(e)),t.replaceChildren(e)}initialize(){this.rootContainer=document.querySelector(this.rootSelector),this.context=this.rootContainer.dataset.context??"",this.controller=this.rootContainer.dataset.controller??"",this.registerInstallToolRoutes(),new RegularEvent("click",(e=>{e.preventDefault(),this.logout()})).delegateTo(document,".t3js-login-lockInstallTool"),new RegularEvent("click",(e=>{e.preventDefault(),this.login()})).delegateTo(document,".t3js-login-login"),new RegularEvent("keydown",(e=>{"Enter"===e.key&&(e.preventDefault(),this.login())})).delegateTo(document,"#t3-install-form-password"),new RegularEvent("click",((e,t)=>{e.preventDefault();const o=t.dataset.import,n=t.dataset.inline;if(void 0!==n&&1===parseInt(n,10))import(o).then((({default:e})=>{e.initialize(t)}));else{const e=t.closest(".card").querySelector(".card-title").innerHTML,n=t.dataset.modalSize||Modal.sizes.large;Modal.advanced({type:Modal.types.default,title:e,size:n,content:html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`,additionalCssClasses:["install-tool-modal"],staticBackdrop:!0,callback:e=>{import(o).then((({default:t})=>{t.initialize(e)}))}})}})).delegateTo(document,".card .btn"),"backend"===this.context?this.executeSilentConfigurationUpdate():this.preAccessCheck()}registerInstallToolRoutes(){void 0===TYPO3.settings&&(TYPO3.settings={ajaxUrls:{icons:window.location.origin+window.location.pathname+"?install[controller]=icon&install[action]=getIcon",icons_cache:window.location.origin+window.location.pathname+"?install[controller]=icon&install[action]=getCacheIdentifier"}})}getUrl(e,t,o){const n=new URL(location.href,window.origin);if(n.searchParams.set("install[controller]",t??this.controller),n.searchParams.set("install[context]",this.context),void 0!==e&&n.searchParams.set("install[action]",e),void 0!==o)for(const[e,t]of Object.entries(o))n.searchParams.set(e,t);return n.toString()}executeSilentConfigurationUpdate(){this.updateLoadingInfo("Checking session and executing silent configuration update"),new AjaxRequest(this.getUrl("executeSilentConfigurationUpdate","layout")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success?this.executeSilentTemplateFileUpdate():this.executeSilentConfigurationUpdate()}),(e=>{this.handleAjaxError(e)}))}executeSilentTemplateFileUpdate(){this.updateLoadingInfo("Checking session and executing silent template file update"),new AjaxRequest(this.getUrl("executeSilentTemplateFileUpdate","layout")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success?this.executeSilentExtensionConfigurationSynchronization():this.executeSilentTemplateFileUpdate()}),(e=>{this.handleAjaxError(e)}))}executeSilentExtensionConfigurationSynchronization(){this.updateLoadingInfo("Executing silent extension configuration synchronization"),new AjaxRequest(this.getUrl("executeSilentExtensionConfigurationSynchronization","layout")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success?this.loadMainLayout():this.setContent(InfoBox.create(Severity.error,"Something went wrong"))}),(e=>{this.handleAjaxError(e)}))}loadMainLayout(){this.updateLoadingInfo("Loading main layout"),new AjaxRequest(this.getUrl("mainLayout","layout",{"install[module]":this.controller})).get({cache:"no-cache"}).then((async e=>{const t=await e.resolve();!0===t.success&&"undefined"!==t.html&&t.html.length>0?(this.rootContainer.innerHTML=t.html,"backend"!==this.context&&(this.rootContainer.querySelector('[data-installroute-controller="'+this.controller+'"]').classList.add("modulemenu-action-active"),this.registerScaffoldEvents()),this.loadCards()):this.rootContainer.replaceChildren(InfoBox.create(Severity.error,"Something went wrong"))}),(e=>{this.handleAjaxError(e)}))}async handleAjaxError(e,t){if(403===e.response.status)"backend"===this.context?this.rootContainer.replaceChildren(InfoBox.create(Severity.error,"The Install Tool session expired. Please reload the backend and try again.")):this.checkEnableInstallToolFile();else{const o='<div class="t3js-infobox callout callout-sm callout-danger"><h4 class="callout-title">Something went wrong</h4><div class="callout-body"><p>Please use <b><a href="'+this.getUrl(void 0,"upgrade")+'">Check for broken extensions</a></b> to see if a loaded extension breaks this part of the Install Tool and unload it.</p><p>The box below may additionally reveal further details on what went wrong depending on your debug settings. It may help to temporarily switch to debug mode using <b>Settings > Configuration Presets > Debug settings.</b></p><p>If this error happens at an early state and no full exception back trace is shown, it may also help to manually increase debugging output in <strong>%config-dir%/system/settings.php</strong>:<code>[\'BE\'][\'debug\'] => true</code>, <code>[\'SYS\'][\'devIPmask\'] => \'*\'</code>, <code>[\'SYS\'][\'displayErrors\'] => 1</code>,<code>[\'SYS\'][\'exceptionalErrors\'] => 12290</code></p></div></div><div class="panel-group" role="tablist" aria-multiselectable="true"><div class="panel panel-default searchhit"><div class="panel-heading" role="tab" id="heading-error"><h3 class="panel-title"><a role="button" data-bs-toggle="collapse" data-bs-parent="#accordion" href="#collapse-error" aria-expanded="true" aria-controls="collapse-error" class="collapsed"><span class="caret"></span><strong>Ajax error</strong></a></h3></div><div id="collapse-error" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading-error"><div class="panel-body">'+await e.response.text()+"</div></div></div></div>";void 0!==t?t.innerHTML=o:this.rootContainer.innerHTML=o}}checkEnableInstallToolFile(){new AjaxRequest(this.getUrl("checkEnableInstallToolFile")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success?this.checkLogin():this.showEnableInstallTool()}),(e=>{this.handleAjaxError(e)}))}showEnableInstallTool(){new AjaxRequest(this.getUrl("showEnableInstallToolFile")).get({cache:"no-cache"}).then((async e=>{const t=await e.resolve();!0===t.success&&(this.rootContainer.innerHTML=t.html)}),(e=>{this.handleAjaxError(e)}))}checkLogin(){new AjaxRequest(this.getUrl("checkLogin")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success?this.loadMainLayout():this.showLogin()}),(e=>{this.handleAjaxError(e)}))}showLogin(){new AjaxRequest(this.getUrl("showLogin")).get({cache:"no-cache"}).then((async e=>{const t=await e.resolve();!0===t.success&&(this.rootContainer.innerHTML=t.html)}),(e=>{this.handleAjaxError(e)}))}login(){const e=document.querySelector(".t3js-login-output"),t=document.createElement("typo3-install-progress-bar");e.replaceChildren(t),new AjaxRequest(this.getUrl()).post({install:{action:"login",token:document.querySelector("[data-login-token]").dataset.loginToken,password:document.querySelector(".t3-install-form-input-text").value}}).then((async t=>{const o=await t.resolve();!0===o.success?this.executeSilentConfigurationUpdate():o.status.forEach((t=>{e.replaceChildren(InfoBox.create(t.severity,t.title,t.message))}))}),(e=>{this.handleAjaxError(e)}))}logout(){new AjaxRequest(this.getUrl("logout")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success&&this.showEnableInstallTool()}),(e=>{this.handleAjaxError(e)}))}loadCards(){new AjaxRequest(this.getUrl("cards")).get({cache:"no-cache"}).then((async e=>{const t=await e.resolve();!0===t.success&&"undefined"!==t.html&&t.html.length>0?this.setContent(t.html):this.setContent(InfoBox.create(Severity.error,"Something went wrong"))}),(e=>{this.handleAjaxError(e)}))}registerScaffoldEvents(){localStorage.getItem("typo3-install-modulesCollapsed")||localStorage.setItem("typo3-install-modulesCollapsed","false"),this.toggleMenu("true"===localStorage.getItem("typo3-install-modulesCollapsed")),document.querySelector(this.scaffoldMenuToggleSelector).addEventListener("click",(e=>{e.preventDefault(),this.toggleMenu()})),document.querySelector(this.scaffoldContentOverlaySelector).addEventListener("click",(e=>{e.preventDefault(),this.toggleMenu(!0)})),document.querySelectorAll("[data-installroute-controller]").forEach((e=>{e.addEventListener("click",(()=>{window.innerWidth<768&&localStorage.setItem("typo3-install-modulesCollapsed","true")}))}))}toggleMenu(e){const t=document.querySelector(this.scaffoldSelector),o="scaffold-modulemenu-expanded";void 0===e&&(e=t.classList.contains(o)),t.classList.toggle(o,!e),localStorage.setItem("typo3-install-modulesCollapsed",e?"true":"false")}updateLoadingInfo(e){const t=this.rootContainer.querySelector("#t3js-ui-block-detail");void 0!==t&&t instanceof HTMLElement&&(t.innerText=e)}preAccessCheck(){this.updateLoadingInfo("Execute pre access check"),new AjaxRequest(this.getUrl("preAccessCheck","layout")).get({cache:"no-cache"}).then((async e=>{const t=await e.resolve();t.installToolLocked?this.checkEnableInstallToolFile():t.isAuthorized?this.executeSilentConfigurationUpdate():this.showLogin()}),(e=>{this.handleAjaxError(e)}))}}export default new Router; \ No newline at end of file +import{html}from"lit";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import{default as Modal}from"@typo3/backend/modal.js";import{InfoBox}from"@typo3/install/renderable/info-box.js";import"@typo3/install/renderable/progress-bar.js";import Severity from"@typo3/install/renderable/severity.js";import"@typo3/backend/element/spinner-element.js";import RegularEvent from"@typo3/core/event/regular-event.js";class Router{constructor(){this.rootSelector=".t3js-body",this.contentSelector=".t3js-module-body",this.scaffoldSelector=".t3js-scaffold",this.scaffoldContentOverlaySelector=".t3js-scaffold-content-overlay",this.scaffoldMenuToggleSelector=".t3js-topbar-button-modulemenu"}setContent(e){const t=this.rootContainer.querySelector(this.contentSelector);"string"==typeof e&&(e=document.createRange().createContextualFragment(e)),t.replaceChildren(e)}initialize(){this.rootContainer=document.querySelector(this.rootSelector),this.context=this.rootContainer.dataset.context??"",this.controller=this.rootContainer.dataset.controller??"",this.registerInstallToolRoutes(),new RegularEvent("click",(e=>{e.preventDefault(),this.logout()})).delegateTo(document,".t3js-login-lockInstallTool"),new RegularEvent("click",(e=>{e.preventDefault(),this.login()})).delegateTo(document,".t3js-login-login"),new RegularEvent("keydown",(e=>{"Enter"===e.key&&(e.preventDefault(),this.login())})).delegateTo(document,"#t3-install-form-password"),new RegularEvent("click",((e,t)=>{e.preventDefault();const o=t.dataset.import,n=t.dataset.inline;if(void 0!==n&&1===parseInt(n,10))import(o).then((({default:e})=>{e.initialize(t)}));else{const e=t.closest(".card").querySelector(".card-title").innerHTML,n=t.dataset.modalSize||Modal.sizes.large;Modal.advanced({type:Modal.types.default,title:e,size:n,content:html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>`,additionalCssClasses:["install-tool-modal"],staticBackdrop:!0,callback:e=>{import(o).then((({default:t})=>{t.initialize(e)}))}})}})).delegateTo(document,".card .btn"),"backend"===this.context?this.executeSilentConfigurationUpdate():this.preAccessCheck()}registerInstallToolRoutes(){void 0===TYPO3.settings&&(TYPO3.settings={ajaxUrls:{icons:window.location.origin+window.location.pathname+"?install[controller]=icon&install[action]=getIcon",icons_cache:window.location.origin+window.location.pathname+"?install[controller]=icon&install[action]=getCacheIdentifier"}})}getUrl(e,t,o){const n=new URL(location.href,window.origin);if(n.searchParams.set("install[controller]",t??this.controller),n.searchParams.set("install[context]",this.context),void 0!==e&&n.searchParams.set("install[action]",e),void 0!==o)for(const[e,t]of Object.entries(o))n.searchParams.set(e,t);return n.toString()}executeSilentConfigurationUpdate(){this.updateLoadingInfo("Checking session and executing silent configuration update"),new AjaxRequest(this.getUrl("executeSilentConfigurationUpdate","layout")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success?this.executeSilentTemplateFileUpdate():this.executeSilentConfigurationUpdate()}),(e=>{this.handleAjaxError(e)}))}executeSilentTemplateFileUpdate(){this.updateLoadingInfo("Checking session and executing silent template file update"),new AjaxRequest(this.getUrl("executeSilentTemplateFileUpdate","layout")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success?this.executeSilentExtensionConfigurationSynchronization():this.executeSilentTemplateFileUpdate()}),(e=>{this.handleAjaxError(e)}))}executeSilentExtensionConfigurationSynchronization(){this.updateLoadingInfo("Executing silent extension configuration synchronization"),new AjaxRequest(this.getUrl("executeSilentExtensionConfigurationSynchronization","layout")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success?this.loadMainLayout():this.setContent(InfoBox.create(Severity.error,"Something went wrong"))}),(e=>{this.handleAjaxError(e)}))}loadMainLayout(){this.updateLoadingInfo("Loading main layout"),new AjaxRequest(this.getUrl("mainLayout","layout",{"install[module]":this.controller})).get({cache:"no-cache"}).then((async e=>{const t=await e.resolve();!0===t.success&&"undefined"!==t.html&&t.html.length>0?(this.rootContainer.innerHTML=t.html,"backend"!==this.context&&(this.rootContainer.querySelector('[data-installroute-controller="'+this.controller+'"]').classList.add("modulemenu-action-active"),this.registerScaffoldEvents()),this.loadCards()):this.rootContainer.replaceChildren(InfoBox.create(Severity.error,"Something went wrong"))}),(e=>{this.handleAjaxError(e)}))}async handleAjaxError(e,t){if(403===e.response.status)"backend"===this.context?this.rootContainer.replaceChildren(InfoBox.create(Severity.error,"The Install Tool session expired. Please reload the backend and try again.")):this.checkEnableInstallToolFile();else{const o='<div class="t3js-infobox callout callout-sm callout-danger"><h4 class="callout-title">Something went wrong</h4><div class="callout-body"><p>Please use <b><a href="'+this.getUrl(void 0,"upgrade")+'">Check for broken extensions</a></b> to see if a loaded extension breaks this part of the Install Tool and unload it.</p><p>The box below may additionally reveal further details on what went wrong depending on your debug settings. It may help to temporarily switch to debug mode using <b>Settings > Configuration Presets > Debug settings.</b></p><p>If this error happens at an early state and no full exception back trace is shown, it may also help to manually increase debugging output in <strong>%config-dir%/system/settings.php</strong>:<code>[\'BE\'][\'debug\'] => true</code>, <code>[\'SYS\'][\'devIPmask\'] => \'*\'</code>, <code>[\'SYS\'][\'displayErrors\'] => 1</code>,<code>[\'SYS\'][\'exceptionalErrors\'] => 12290</code></p></div></div><div class="panel-group" role="tablist" aria-multiselectable="true"><div class="panel panel-default searchhit"><div class="panel-heading" role="tab" id="heading-error"><h3 class="panel-title"><a role="button" data-bs-toggle="collapse" data-bs-parent="#accordion" href="#collapse-error" aria-expanded="true" aria-controls="collapse-error" class="collapsed"><span class="caret"></span><strong>Ajax error</strong></a></h3></div><div id="collapse-error" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading-error"><div class="panel-body">'+await e.response.text()+"</div></div></div></div>";void 0!==t?t.innerHTML=o:this.rootContainer.innerHTML=o}}checkEnableInstallToolFile(){new AjaxRequest(this.getUrl("checkEnableInstallToolFile")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success?this.checkLogin():this.showEnableInstallTool()}),(e=>{this.handleAjaxError(e)}))}showEnableInstallTool(){new AjaxRequest(this.getUrl("showEnableInstallToolFile")).get({cache:"no-cache"}).then((async e=>{const t=await e.resolve();!0===t.success&&(this.rootContainer.innerHTML=t.html)}),(e=>{this.handleAjaxError(e)}))}checkLogin(){new AjaxRequest(this.getUrl("checkLogin")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success?this.loadMainLayout():this.showLogin()}),(e=>{this.handleAjaxError(e)}))}showLogin(){new AjaxRequest(this.getUrl("showLogin")).get({cache:"no-cache"}).then((async e=>{const t=await e.resolve();!0===t.success&&(this.rootContainer.innerHTML=t.html)}),(e=>{this.handleAjaxError(e)}))}login(){const e=document.querySelector(".t3js-login-output"),t=document.createElement("typo3-install-progress-bar");e.replaceChildren(t),new AjaxRequest(this.getUrl()).post({install:{action:"login",token:document.querySelector("[data-login-token]").dataset.loginToken,password:document.querySelector(".t3-install-form-input-text").value}}).then((async t=>{const o=await t.resolve();!0===o.success?this.executeSilentConfigurationUpdate():o.status.forEach((t=>{e.replaceChildren(InfoBox.create(t.severity,t.title,t.message))}))}),(e=>{this.handleAjaxError(e)}))}logout(){new AjaxRequest(this.getUrl("logout")).get({cache:"no-cache"}).then((async e=>{!0===(await e.resolve()).success&&this.showEnableInstallTool()}),(e=>{this.handleAjaxError(e)}))}loadCards(){new AjaxRequest(this.getUrl("cards")).get({cache:"no-cache"}).then((async e=>{const t=await e.resolve();!0===t.success&&"undefined"!==t.html&&t.html.length>0?this.setContent(t.html):this.setContent(InfoBox.create(Severity.error,"Something went wrong"))}),(e=>{this.handleAjaxError(e)}))}registerScaffoldEvents(){localStorage.getItem("typo3-install-modulesCollapsed")||localStorage.setItem("typo3-install-modulesCollapsed","false"),this.toggleMenu("true"===localStorage.getItem("typo3-install-modulesCollapsed")),document.querySelector(this.scaffoldMenuToggleSelector).addEventListener("click",(e=>{e.preventDefault(),this.toggleMenu()})),document.querySelector(this.scaffoldContentOverlaySelector).addEventListener("click",(e=>{e.preventDefault(),this.toggleMenu(!0)})),document.querySelectorAll("[data-installroute-controller]").forEach((e=>{e.addEventListener("click",(()=>{window.innerWidth<768&&localStorage.setItem("typo3-install-modulesCollapsed","true")}))}))}toggleMenu(e){const t=document.querySelector(this.scaffoldSelector),o="scaffold-modulemenu-expanded";void 0===e&&(e=t.classList.contains(o)),t.classList.toggle(o,!e),localStorage.setItem("typo3-install-modulesCollapsed",e?"true":"false")}updateLoadingInfo(e){const t=this.rootContainer.querySelector("#t3js-ui-block-detail");void 0!==t&&t instanceof HTMLElement&&(t.innerText=e)}preAccessCheck(){this.updateLoadingInfo("Execute pre access check"),new AjaxRequest(this.getUrl("preAccessCheck","layout")).get({cache:"no-cache"}).then((async e=>{const t=await e.resolve();t.installToolLocked?this.checkEnableInstallToolFile():t.isAuthorized?this.executeSilentConfigurationUpdate():this.showLogin()}),(e=>{this.handleAjaxError(e)}))}}export default new Router; \ No newline at end of file diff --git a/typo3/sysext/tstemplate/Resources/Public/JavaScript/template-analyzer.js b/typo3/sysext/tstemplate/Resources/Public/JavaScript/template-analyzer.js index f411a0ef9f253410ef12f9329d012bef3c626ab3..0dfcd81b1594fb3a9a1c7ac992f800405fa4c1da 100644 --- a/typo3/sysext/tstemplate/Resources/Public/JavaScript/template-analyzer.js +++ b/typo3/sysext/tstemplate/Resources/Public/JavaScript/template-analyzer.js @@ -10,7 +10,7 @@ * * The TYPO3 project - inspiring people to share! */ -import DocumentService from"@typo3/core/document-service.js";import{default as Modal}from"@typo3/backend/modal.js";import{topLevelModuleImport}from"@typo3/backend/utility/top-level-module-import.js";import{html}from"lit";import{until}from"lit/directives/until.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";class TemplateAnalyzer{constructor(){this.registerEventListeners()}async registerEventListeners(){await DocumentService.ready(),document.querySelectorAll(".t3js-typoscript-analyzer-modal").forEach((e=>{e.addEventListener("click",(t=>{t.preventDefault();const o=Modal.types.default,r=e.dataset.modalTitle||e.textContent.trim(),a=e.getAttribute("href"),l=Modal.sizes.large,i=html`${until(this.fetchModalContent(a),html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`)}`;Modal.advanced({type:o,title:r,size:l,content:i})}))}))}async fetchModalContent(e){topLevelModuleImport("@typo3/backend/code-editor/element/code-mirror-element.js");const t=await new AjaxRequest(e).get(),o=await t.resolve();return html` +import DocumentService from"@typo3/core/document-service.js";import{default as Modal}from"@typo3/backend/modal.js";import{topLevelModuleImport}from"@typo3/backend/utility/top-level-module-import.js";import{html}from"lit";import{until}from"lit/directives/until.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";class TemplateAnalyzer{constructor(){this.registerEventListeners()}async registerEventListeners(){await DocumentService.ready(),document.querySelectorAll(".t3js-typoscript-analyzer-modal").forEach((e=>{e.addEventListener("click",(t=>{t.preventDefault();const o=Modal.types.default,r=e.dataset.modalTitle||e.textContent.trim(),a=e.getAttribute("href"),l=Modal.sizes.large,i=html`${until(this.fetchModalContent(a),html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>`)}`;Modal.advanced({type:o,title:r,size:l,content:i})}))}))}async fetchModalContent(e){topLevelModuleImport("@typo3/backend/code-editor/element/code-mirror-element.js");const t=await new AjaxRequest(e).get(),o=await t.resolve();return html` <typo3-t3editor-codemirror .mode="${{name:"@typo3/backend/code-editor/language/typoscript.js",flags:2,exportName:"typoscript",items:[{type:"invoke",args:[]}]}}" nolazyload readonly class="flex-grow-1 mh-100"> <textarea readonly disabled class="form-control">${o}</textarea> </typo3-t3editor-codemirror> diff --git a/typo3/sysext/workspaces/Resources/Public/JavaScript/workspaces.js b/typo3/sysext/workspaces/Resources/Public/JavaScript/workspaces.js index a37f40abae5db86a47383ff88ed9ba1bbe742192..f088113094286c57dcd89c95cae60bf608492550 100644 --- a/typo3/sysext/workspaces/Resources/Public/JavaScript/workspaces.js +++ b/typo3/sysext/workspaces/Resources/Public/JavaScript/workspaces.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import{SeverityEnum}from"@typo3/backend/enum/severity.js";import NProgress from"nprogress";import{default as Modal}from"@typo3/backend/modal.js";import{html}from"lit";export default class Workspaces{constructor(){this.tid=0}renderSendToStageWindow(e){const t=e[0].result,a=Modal.advanced({title:TYPO3.lang.actionSendToStage,content:html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`,severity:SeverityEnum.info,buttons:[{text:TYPO3.lang.cancel,active:!0,btnClass:"btn-default",name:"cancel",trigger:()=>{a.hideModal()}},{text:TYPO3.lang.ok,btnClass:"btn-primary",name:"ok"}],callback:e=>{const a=e.ownerDocument.createElement("typo3-workspaces-send-to-stage-form");a.data=t,a.TYPO3lang=TYPO3.lang,e.querySelector(".t3js-modal-body").replaceChildren(a)}});return a}sendRemoteRequest(e,t="#workspace-content-wrapper"){return NProgress.configure({parent:t,showSpinner:!1}),NProgress.start(),new AjaxRequest(TYPO3.settings.ajaxUrls.workspace_dispatch).post(e,{headers:{"Content-Type":"application/json; charset=utf-8"}}).finally((()=>NProgress.done()))}generateRemotePayload(e,t={}){return this.generateRemotePayloadBody("RemoteServer",e,t)}generateRemoteMassActionsPayload(e,t={}){return this.generateRemotePayloadBody("MassActions",e,t)}generateRemoteActionsPayload(e,t={}){return this.generateRemotePayloadBody("Actions",e,t)}generateRemotePayloadBody(e,t,a){return a instanceof Array?a.push(TYPO3.settings.Workspaces.token):a=[a,TYPO3.settings.Workspaces.token],{action:e,data:a,method:t,type:"rpc",tid:this.tid++}}} \ No newline at end of file +import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import{SeverityEnum}from"@typo3/backend/enum/severity.js";import NProgress from"nprogress";import{default as Modal}from"@typo3/backend/modal.js";import{html}from"lit";export default class Workspaces{constructor(){this.tid=0}renderSendToStageWindow(e){const t=e[0].result,a=Modal.advanced({title:TYPO3.lang.actionSendToStage,content:html`<div class="modal-loading"><typo3-backend-spinner size="large"></typo3-backend-spinner></div>`,severity:SeverityEnum.info,buttons:[{text:TYPO3.lang.cancel,active:!0,btnClass:"btn-default",name:"cancel",trigger:()=>{a.hideModal()}},{text:TYPO3.lang.ok,btnClass:"btn-primary",name:"ok"}],callback:e=>{const a=e.ownerDocument.createElement("typo3-workspaces-send-to-stage-form");a.data=t,a.TYPO3lang=TYPO3.lang,e.querySelector(".t3js-modal-body").replaceChildren(a)}});return a}sendRemoteRequest(e,t="#workspace-content-wrapper"){return NProgress.configure({parent:t,showSpinner:!1}),NProgress.start(),new AjaxRequest(TYPO3.settings.ajaxUrls.workspace_dispatch).post(e,{headers:{"Content-Type":"application/json; charset=utf-8"}}).finally((()=>NProgress.done()))}generateRemotePayload(e,t={}){return this.generateRemotePayloadBody("RemoteServer",e,t)}generateRemoteMassActionsPayload(e,t={}){return this.generateRemotePayloadBody("MassActions",e,t)}generateRemoteActionsPayload(e,t={}){return this.generateRemotePayloadBody("Actions",e,t)}generateRemotePayloadBody(e,t,a){return a instanceof Array?a.push(TYPO3.settings.Workspaces.token):a=[a,TYPO3.settings.Workspaces.token],{action:e,data:a,method:t,type:"rpc",tid:this.tid++}}} \ No newline at end of file