MDL-82627 AI: Placement Text Editor - Improvement

- Quiz is setting the text editor id in this format: `#q2:1_answer`.
   This will break the querySelector(). We need to update the code to
   escape those colons.
 - Generate AI image requires users to have the capability to upload files.
   A new extra condition is added to verify this one.
This commit is contained in:
Huong Nguyen 2024-09-10 16:00:44 +07:00
parent 7809ad9d96
commit f4860573fa
No known key found for this signature in database
GPG Key ID: 40D88AB693A3E72A
10 changed files with 33 additions and 25 deletions

View File

@ -1,3 +1,3 @@
define("tiny_aiplacement/generatebase",["exports","tiny_aiplacement/loading","core/str","tiny_aiplacement/options","core_ai/policy","core_ai/policymodal","core/custom_interaction_events","./options"],(function(_exports,_loading,_str,_options,_policy,_policymodal,_custom_interaction_events,_options2){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_policy=_interopRequireDefault(_policy),_policymodal=_interopRequireDefault(_policymodal),_custom_interaction_events=_interopRequireDefault(_custom_interaction_events);return _exports.default=class{constructor(editor){var obj,key,value;value=void 0,(key="modalObject")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,this.editor=editor,this.userid=(0,_options.getUserId)(editor),this.contextid=(0,_options.getContextId)(editor),this.responseObj=null}async displayContentModal(){if(_policy.default.preconfigurePolicyState(this.userid,(0,_options2.isPolicyAgreed)(this.editor)),await _policy.default.getPolicyStatus(this.userid))this.modalObject=await this.setupModal();else{const policyModal=await _policymodal.default.create();policyModal.getModal().on(_custom_interaction_events.default.events.activate,policyModal.getActionSelector("save"),(()=>{this.displayContentModal()}))}}getModalClass(){throw new Error("Method 'getModalClass' must be implemented.")}async setupModal(){const modal=this.getModalClass().create({templateContext:{elementid:this.editor.id}});return this.addContentEventListeners(modal),modal}async addContentEventListeners(modal){const root=(await modal).getRoot()[0];root.addEventListener("click",(e=>{this.handleContentModalClick(e,root)})),this.setupPromptArea(root),this.hideLoadingSpinner(root)}handleContentModalClick(){throw new Error("Method handleContentModalClick must be implemented.")}hideLoadingSpinner(root){const loadingSpinnerDiv=root.querySelector("#".concat(this.editor.id,"_tiny_aiplacement_spinner"));loadingSpinnerDiv.classList.add("hidden"),loadingSpinnerDiv.classList.remove("tiny-aiplacement-loading-spinner-container")}async displayLoading(root,submitBtn){let removeClass=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;const loadingSpinnerDiv=root.querySelector("#".concat(this.editor.id,"_tiny_aiplacement_spinner")),overlayDiv=root.querySelector("#".concat(this.editor.id,"_tiny_aiplacement_overlay")),blurDiv=root.querySelector("#".concat(this.editor.id,"_tiny_aiplacement_blur")),loadingTextDiv=root.querySelector("#".concat(this.editor.id,"_tiny_aiplacement_loading_text")),actionButtons=root.querySelectorAll(".tiny-aiplacement-generate-footer button");(0,_loading.loadingMessages)(loadingTextDiv),removeClass&&loadingSpinnerDiv.classList.remove(removeClass),loadingSpinnerDiv.classList.remove("hidden"),overlayDiv.classList.remove("hidden"),blurDiv.classList.add("tiny-aiplacement-blur"),submitBtn.innerHTML=await(0,_str.getString)("generating","tiny_aiplacement"),actionButtons&&actionButtons.forEach((button=>{button.disabled=!0}))}async hideLoading(root,submitBtn){const loadingSpinnerDiv=root.querySelector("#".concat(this.editor.id,"_tiny_aiplacement_spinner")),overlayDiv=root.querySelector("#".concat(this.editor.id,"_tiny_aiplacement_overlay")),blurDiv=root.querySelector("#".concat(this.editor.id,"_tiny_aiplacement_blur")),actionButtons=root.querySelectorAll(".tiny-aiplacement-generate-footer button");loadingSpinnerDiv&&loadingSpinnerDiv.classList.add("hidden"),overlayDiv&&overlayDiv.classList.add("hidden"),blurDiv&&blurDiv.classList.remove("tiny-aiplacement-blur"),submitBtn.innerHTML=await(0,_str.getString)("regenerate","tiny_aiplacement"),actionButtons&&actionButtons.forEach((button=>{button.disabled=!1}))}},_exports.default}));
define("tiny_aiplacement/generatebase",["exports","tiny_aiplacement/loading","core/str","tiny_aiplacement/options","core_ai/policy","core_ai/policymodal","core/custom_interaction_events","./options"],(function(_exports,_loading,_str,_options,_policy,_policymodal,_custom_interaction_events,_options2){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_policy=_interopRequireDefault(_policy),_policymodal=_interopRequireDefault(_policymodal),_custom_interaction_events=_interopRequireDefault(_custom_interaction_events);return _exports.default=class{constructor(editor){var obj,key,value;value=void 0,(key="modalObject")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,this.editor=editor,this.userid=(0,_options.getUserId)(editor),this.contextid=(0,_options.getContextId)(editor),this.responseObj=null}async displayContentModal(){if(_policy.default.preconfigurePolicyState(this.userid,(0,_options2.isPolicyAgreed)(this.editor)),await _policy.default.getPolicyStatus(this.userid))this.modalObject=await this.setupModal();else{const policyModal=await _policymodal.default.create();policyModal.getModal().on(_custom_interaction_events.default.events.activate,policyModal.getActionSelector("save"),(()=>{this.displayContentModal()}))}}getModalClass(){throw new Error("Method 'getModalClass' must be implemented.")}async setupModal(){const modal=this.getModalClass().create({templateContext:{elementid:this.editor.id}});return this.addContentEventListeners(modal),modal}async addContentEventListeners(modal){const root=(await modal).getRoot()[0];root.addEventListener("click",(e=>{this.handleContentModalClick(e,root)})),this.setupPromptArea(root),this.hideLoadingSpinner(root)}handleContentModalClick(){throw new Error("Method handleContentModalClick must be implemented.")}hideLoadingSpinner(root){const loadingSpinnerDiv=root.querySelector('[id="'.concat(this.editor.id,'_tiny_aiplacement_spinner"]'));loadingSpinnerDiv.classList.add("hidden"),loadingSpinnerDiv.classList.remove("tiny-aiplacement-loading-spinner-container")}async displayLoading(root,submitBtn){let removeClass=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;const loadingSpinnerDiv=root.querySelector('[id="'.concat(this.editor.id,'_tiny_aiplacement_spinner"]')),overlayDiv=root.querySelector('[id="'.concat(this.editor.id,'_tiny_aiplacement_overlay"]')),blurDiv=root.querySelector('[id="'.concat(this.editor.id,'_tiny_aiplacement_blur"]')),loadingTextDiv=root.querySelector('[id="'.concat(this.editor.id,'_tiny_aiplacement_loading_text"]')),actionButtons=root.querySelectorAll(".tiny-aiplacement-generate-footer button");(0,_loading.loadingMessages)(loadingTextDiv),removeClass&&loadingSpinnerDiv.classList.remove(removeClass),loadingSpinnerDiv.classList.remove("hidden"),overlayDiv.classList.remove("hidden"),blurDiv.classList.add("tiny-aiplacement-blur"),submitBtn.innerHTML=await(0,_str.getString)("generating","tiny_aiplacement"),actionButtons&&actionButtons.forEach((button=>{button.disabled=!0}))}async hideLoading(root,submitBtn){const loadingSpinnerDiv=root.querySelector('[id="'.concat(this.editor.id,'_tiny_aiplacement_spinner"]')),overlayDiv=root.querySelector('[id="'.concat(this.editor.id,'_tiny_aiplacement_overlay"]')),blurDiv=root.querySelector('[id="'.concat(this.editor.id,'_tiny_aiplacement_blur"]')),actionButtons=root.querySelectorAll(".tiny-aiplacement-generate-footer button");loadingSpinnerDiv&&loadingSpinnerDiv.classList.add("hidden"),overlayDiv&&overlayDiv.classList.add("hidden"),blurDiv&&blurDiv.classList.remove("tiny-aiplacement-blur"),submitBtn.innerHTML=await(0,_str.getString)("regenerate","tiny_aiplacement"),actionButtons&&actionButtons.forEach((button=>{button.disabled=!1}))}},_exports.default}));
//# sourceMappingURL=generatebase.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
define("tiny_aiplacement/generateimage",["exports","tiny_aiplacement/imagemodal","core/ajax","core/str","core/templates","./mediaimage","tiny_aiplacement/options","tiny_aiplacement/generatebase"],(function(_exports,_imagemodal,_ajax,_str,_templates,_mediaimage,_options,_generatebase){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_imagemodal=_interopRequireDefault(_imagemodal),_ajax=_interopRequireDefault(_ajax),_templates=_interopRequireDefault(_templates),_mediaimage=_interopRequireDefault(_mediaimage),_generatebase=_interopRequireDefault(_generatebase);class GenerateImage extends _generatebase.default{constructor(){super(...arguments),_defineProperty(this,"SELECTORS",{GENERATEBUTTON:()=>"#".concat(this.editor.id,"_tiny_aiplacement_generatebutton"),PROMPTAREA:()=>"#".concat(this.editor.id,"_tiny_aiplacement_imageprompt"),IMAGECONTAINER:()=>"#".concat(this.editor.id,"_tiny_aiplacement_generate_image"),GENERATEBTN:'[data-action="generate"]',INSERTBTN:'[data-action="inserter"]',BACKTBTN:'[data-action="back"]',GENERATEDIMAGE:()=>"#".concat(this.editor.id,"_tiny_generated_image")}),_defineProperty(this,"imageURL",null)}getModalClass(){return _imagemodal.default}handleContentModalClick(e,root){const actions={generate:()=>this.handleSubmit(root,e.target),inserter:()=>this.handleInsert(),cancel:()=>this.modalObject.destroy(),back:()=>{this.modalObject.destroy(),this.displayContentModal()}},actionKey=Object.keys(actions).find((key=>e.target.closest('[data-action="'.concat(key,'"]'))));actionKey&&(e.preventDefault(),actions[actionKey]())}setupPromptArea(root){const generateBtn=root.querySelector(this.SELECTORS.GENERATEBUTTON()),promptArea=root.querySelector(this.SELECTORS.PROMPTAREA());promptArea.addEventListener("input",(()=>{generateBtn.disabled=""===promptArea.value.trim()}))}async handleSubmit(root,submitBtn){await this.displayLoading(root,submitBtn);const request={methodname:"aiplacement_editor_generate_image",args:this.getDisplayArgs(root)};try{this.responseObj=await _ajax.default.call([request])[0],this.responseObj.error?this.handleGenerationError(root,submitBtn,""):(await this.displayGeneratedImage(root),this.hideLoading(root,submitBtn),window.console.log(this.responseObj))}catch(error){this.handleGenerationError(root,submitBtn,"")}}async handleInsert(){const mediaImage=new _mediaimage.default(this.editor,this.imageURL,this.promptText);await mediaImage.displayDialogue(),this.modalObject.destroy()}async handleGenerationError(root,submitBtn){let errorMessage=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";errorMessage||(errorMessage=await(0,_str.getString)("errorgeneral","tiny_aiplacement")),this.hideLoading(root,submitBtn),this.modalObject.setBody(_templates.default.render("tiny_aiplacement/modalbodyerror",{errorMessage:errorMessage}));const backBtn=root.querySelector(this.SELECTORS.BACKTBTN),generateBtn=root.querySelector(this.SELECTORS.GENERATEBUTTON());backBtn.classList.remove("hidden"),generateBtn.classList.add("hidden")}async displayGeneratedImage(root){const imageDisplayContainer=root.querySelector(this.SELECTORS.IMAGECONTAINER()),insertBtn=root.querySelector(this.SELECTORS.INSERTBTN);this.imageURL=this.responseObj.drafturl,imageDisplayContainer.innerHTML=await _templates.default.render("tiny_aiplacement/image",{url:this.responseObj.drafturl,elementid:this.editor.id,alt:this.promptText});const imagElement=root.querySelector(this.SELECTORS.GENERATEDIMAGE());return new Promise(((resolve,reject)=>{imagElement.onload=()=>{insertBtn.classList.remove("hidden"),resolve()},imagElement.onerror=error=>{reject(error)}}))}getDisplayArgs(root){const contextId=(0,_options.getContextId)(this.editor),promptText=root.querySelector(this.SELECTORS.PROMPTAREA()).value;this.promptText=promptText;return{contextid:contextId,prompttext:promptText,aspectratio:this.getSelectedRadioValue("aspect-ratio","square"),quality:this.getSelectedRadioValue("quality","standard")?"hd":"standard",numimages:1}}getSelectedRadioValue(radioName){let defaultValue=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;const radios=document.getElementsByName(radioName);for(const radio of radios)if(radio.checked)return radio.value;return defaultValue}}return _exports.default=GenerateImage,_exports.default}));
define("tiny_aiplacement/generateimage",["exports","tiny_aiplacement/imagemodal","core/ajax","core/str","core/templates","./mediaimage","tiny_aiplacement/options","tiny_aiplacement/generatebase"],(function(_exports,_imagemodal,_ajax,_str,_templates,_mediaimage,_options,_generatebase){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_imagemodal=_interopRequireDefault(_imagemodal),_ajax=_interopRequireDefault(_ajax),_templates=_interopRequireDefault(_templates),_mediaimage=_interopRequireDefault(_mediaimage),_generatebase=_interopRequireDefault(_generatebase);class GenerateImage extends _generatebase.default{constructor(){super(...arguments),_defineProperty(this,"SELECTORS",{GENERATEBUTTON:()=>'[id="'.concat(this.editor.id,'_tiny_aiplacement_generatebutton"]'),PROMPTAREA:()=>'[id="'.concat(this.editor.id,'_tiny_aiplacement_imageprompt"]'),IMAGECONTAINER:()=>'[id="'.concat(this.editor.id,'_tiny_aiplacement_generate_image"]'),GENERATEBTN:'[data-action="generate"]',INSERTBTN:'[data-action="inserter"]',BACKTBTN:'[data-action="back"]',GENERATEDIMAGE:()=>'[id="'.concat(this.editor.id,'_tiny_generated_image"]')}),_defineProperty(this,"imageURL",null)}getModalClass(){return _imagemodal.default}handleContentModalClick(e,root){const actions={generate:()=>this.handleSubmit(root,e.target),inserter:()=>this.handleInsert(),cancel:()=>this.modalObject.destroy(),back:()=>{this.modalObject.destroy(),this.displayContentModal()}},actionKey=Object.keys(actions).find((key=>e.target.closest('[data-action="'.concat(key,'"]'))));actionKey&&(e.preventDefault(),actions[actionKey]())}setupPromptArea(root){const generateBtn=root.querySelector(this.SELECTORS.GENERATEBUTTON()),promptArea=root.querySelector(this.SELECTORS.PROMPTAREA());promptArea.addEventListener("input",(()=>{generateBtn.disabled=""===promptArea.value.trim()}))}async handleSubmit(root,submitBtn){await this.displayLoading(root,submitBtn);const request={methodname:"aiplacement_editor_generate_image",args:this.getDisplayArgs(root)};try{this.responseObj=await _ajax.default.call([request])[0],this.responseObj.error?this.handleGenerationError(root,submitBtn,""):(await this.displayGeneratedImage(root),this.hideLoading(root,submitBtn),window.console.log(this.responseObj))}catch(error){this.handleGenerationError(root,submitBtn,"")}}async handleInsert(){const mediaImage=new _mediaimage.default(this.editor,this.imageURL,this.promptText);await mediaImage.displayDialogue(),this.modalObject.destroy()}async handleGenerationError(root,submitBtn){let errorMessage=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";errorMessage||(errorMessage=await(0,_str.getString)("errorgeneral","tiny_aiplacement")),this.hideLoading(root,submitBtn),this.modalObject.setBody(_templates.default.render("tiny_aiplacement/modalbodyerror",{errorMessage:errorMessage}));const backBtn=root.querySelector(this.SELECTORS.BACKTBTN),generateBtn=root.querySelector(this.SELECTORS.GENERATEBUTTON());backBtn.classList.remove("hidden"),generateBtn.classList.add("hidden")}async displayGeneratedImage(root){const imageDisplayContainer=root.querySelector(this.SELECTORS.IMAGECONTAINER()),insertBtn=root.querySelector(this.SELECTORS.INSERTBTN);this.imageURL=this.responseObj.drafturl,imageDisplayContainer.innerHTML=await _templates.default.render("tiny_aiplacement/image",{url:this.responseObj.drafturl,elementid:this.editor.id,alt:this.promptText});const imagElement=root.querySelector(this.SELECTORS.GENERATEDIMAGE());return new Promise(((resolve,reject)=>{imagElement.onload=()=>{insertBtn.classList.remove("hidden"),resolve()},imagElement.onerror=error=>{reject(error)}}))}getDisplayArgs(root){const contextId=(0,_options.getContextId)(this.editor),promptText=root.querySelector(this.SELECTORS.PROMPTAREA()).value;this.promptText=promptText;return{contextid:contextId,prompttext:promptText,aspectratio:this.getSelectedRadioValue("aspect-ratio","square"),quality:this.getSelectedRadioValue("quality","standard")?"hd":"standard",numimages:1}}getSelectedRadioValue(radioName){let defaultValue=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;const radios=document.getElementsByName(radioName);for(const radio of radios)if(radio.checked)return radio.value;return defaultValue}}return _exports.default=GenerateImage,_exports.default}));
//# sourceMappingURL=generateimage.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
define("tiny_aiplacement/generatetext",["exports","./textmodal","core/ajax","core/str","core/templates","./options","./textmark","./generatebase"],(function(_exports,_textmodal,_ajax,_str,_templates,_options,_textmark,_generatebase){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_textmodal=_interopRequireDefault(_textmodal),_ajax=_interopRequireDefault(_ajax),_templates=_interopRequireDefault(_templates),_textmark=_interopRequireDefault(_textmark),_generatebase=_interopRequireDefault(_generatebase);class GenerateText extends _generatebase.default{constructor(){var obj,key,value;super(...arguments),value={GENERATEBUTTON:()=>"#".concat(this.editor.id,"_tiny_aiplacement_generatebutton"),PROMPTAREA:()=>"#".concat(this.editor.id,"_tiny_aiplacement_textprompt"),RESPONSEWRAPPER:".tiny_aiplacement_textresponse",RESPONSEPLACEHOLDER:".tiny_aiplacement_textresponse_placeholder",GENERATEDRESPONSE:()=>"#".concat(this.editor.id,"_tiny_aiplacement_textresponse"),INSERTBTN:'[data-action="inserter"]',BACKTBTN:'[data-action="back"]'},(key="SELECTORS")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}getModalClass(){return _textmodal.default}handleContentModalClick(e,root){const actions={generate:()=>this.handleSubmit(root,e.target),inserter:()=>this.handleInsert(root,e.target),cancel:()=>this.modalObject.destroy(),back:()=>{this.modalObject.destroy(),this.displayContentModal()}},actionKey=Object.keys(actions).find((key=>e.target.closest('[data-action="'.concat(key,'"]'))));actionKey&&(e.preventDefault(),actions[actionKey]())}setupPromptArea(root){const generateBtn=root.querySelector(this.SELECTORS.GENERATEBUTTON()),promptArea=root.querySelector(this.SELECTORS.PROMPTAREA());promptArea.addEventListener("input",(()=>{generateBtn.disabled=""===promptArea.value.trim()}))}async handleSubmit(root,submitBtn){await this.displayLoading(root,submitBtn);const request={methodname:"aiplacement_editor_generate_text",args:this.getRequestArgs(root)};try{this.responseObj=await _ajax.default.call([request])[0],this.responseObj.error?this.handleGenerationError(root,submitBtn,""):(await this.displayGeneratedText(root),this.hideLoading(root,submitBtn))}catch(error){this.handleGenerationError(root,submitBtn,"")}}async handleInsert(root,submitBtn){await this.displayLoading(root,submitBtn);const generatedResponseDiv=root.querySelector(this.SELECTORS.GENERATEDRESPONSE()),wrappedEditedResponse=await _textmark.default.wrapEditedSections(this.responseObj.generatedcontent,generatedResponseDiv.value);this.responseObj.editedtext=this.replaceLineBreaks(wrappedEditedResponse);const formattedResponse=await _templates.default.render("tiny_aiplacement/textinsert",this.responseObj);this.editor.insertContent(formattedResponse),this.editor.execCommand("mceRepaint"),this.editor.windowManager.close(),this.modalObject.hide()}async handleGenerationError(root,submitBtn){let errorMessage=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";errorMessage||(errorMessage=await(0,_str.getString)("errorgeneral","tiny_aiplacement")),this.modalObject.setBody(_templates.default.render("tiny_aiplacement/modalbodyerror",{errorMessage:errorMessage}));const backBtn=root.querySelector(this.SELECTORS.BACKTBTN),generateBtn=root.querySelector(this.SELECTORS.GENERATEBUTTON());backBtn.classList.remove("hidden"),generateBtn.classList.add("hidden"),this.hideLoading(root,submitBtn)}async displayGeneratedText(root){root.querySelector(this.SELECTORS.INSERTBTN).classList.remove("hidden");root.querySelector(this.SELECTORS.GENERATEDRESPONSE()).value=this.responseObj.generatedcontent;root.querySelector(this.SELECTORS.RESPONSEWRAPPER).classList.remove("hidden");root.querySelector(this.SELECTORS.RESPONSEPLACEHOLDER).classList.add("hidden")}getRequestArgs(root){return{contextid:(0,_options.getContextId)(this.editor),prompttext:root.querySelector(this.SELECTORS.PROMPTAREA()).value}}replaceLineBreaks(text){const textWithBreaks=text.replace(/\n{2,}|\r\n/g,"<br/><br/>").replace(/\n/g,"<br/>");return"<p>".concat(textWithBreaks,"</p>")}}return _exports.default=GenerateText,_exports.default}));
define("tiny_aiplacement/generatetext",["exports","./textmodal","core/ajax","core/str","core/templates","./options","./textmark","./generatebase"],(function(_exports,_textmodal,_ajax,_str,_templates,_options,_textmark,_generatebase){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_textmodal=_interopRequireDefault(_textmodal),_ajax=_interopRequireDefault(_ajax),_templates=_interopRequireDefault(_templates),_textmark=_interopRequireDefault(_textmark),_generatebase=_interopRequireDefault(_generatebase);class GenerateText extends _generatebase.default{constructor(){var obj,key,value;super(...arguments),value={GENERATEBUTTON:()=>'[id="'.concat(this.editor.id,'_tiny_aiplacement_generatebutton"]'),PROMPTAREA:()=>'[id="'.concat(this.editor.id,'_tiny_aiplacement_textprompt"]'),RESPONSEWRAPPER:".tiny_aiplacement_textresponse",RESPONSEPLACEHOLDER:".tiny_aiplacement_textresponse_placeholder",GENERATEDRESPONSE:()=>'[id="'.concat(this.editor.id,'_tiny_aiplacement_textresponse"]'),INSERTBTN:'[data-action="inserter"]',BACKTBTN:'[data-action="back"]'},(key="SELECTORS")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}getModalClass(){return _textmodal.default}handleContentModalClick(e,root){const actions={generate:()=>this.handleSubmit(root,e.target),inserter:()=>this.handleInsert(root,e.target),cancel:()=>this.modalObject.destroy(),back:()=>{this.modalObject.destroy(),this.displayContentModal()}},actionKey=Object.keys(actions).find((key=>e.target.closest('[data-action="'.concat(key,'"]'))));actionKey&&(e.preventDefault(),actions[actionKey]())}setupPromptArea(root){const generateBtn=root.querySelector(this.SELECTORS.GENERATEBUTTON()),promptArea=root.querySelector(this.SELECTORS.PROMPTAREA());promptArea.addEventListener("input",(()=>{generateBtn.disabled=""===promptArea.value.trim()}))}async handleSubmit(root,submitBtn){await this.displayLoading(root,submitBtn);const request={methodname:"aiplacement_editor_generate_text",args:this.getRequestArgs(root)};try{this.responseObj=await _ajax.default.call([request])[0],this.responseObj.error?this.handleGenerationError(root,submitBtn,""):(await this.displayGeneratedText(root),this.hideLoading(root,submitBtn))}catch(error){this.handleGenerationError(root,submitBtn,"")}}async handleInsert(root,submitBtn){await this.displayLoading(root,submitBtn);const generatedResponseDiv=root.querySelector(this.SELECTORS.GENERATEDRESPONSE()),wrappedEditedResponse=await _textmark.default.wrapEditedSections(this.responseObj.generatedcontent,generatedResponseDiv.value);this.responseObj.editedtext=this.replaceLineBreaks(wrappedEditedResponse);const formattedResponse=await _templates.default.render("tiny_aiplacement/textinsert",this.responseObj);this.editor.insertContent(formattedResponse),this.editor.execCommand("mceRepaint"),this.editor.windowManager.close(),this.modalObject.hide()}async handleGenerationError(root,submitBtn){let errorMessage=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";errorMessage||(errorMessage=await(0,_str.getString)("errorgeneral","tiny_aiplacement")),this.modalObject.setBody(_templates.default.render("tiny_aiplacement/modalbodyerror",{errorMessage:errorMessage}));const backBtn=root.querySelector(this.SELECTORS.BACKTBTN),generateBtn=root.querySelector(this.SELECTORS.GENERATEBUTTON());backBtn.classList.remove("hidden"),generateBtn.classList.add("hidden"),this.hideLoading(root,submitBtn)}async displayGeneratedText(root){root.querySelector(this.SELECTORS.INSERTBTN).classList.remove("hidden");root.querySelector(this.SELECTORS.GENERATEDRESPONSE()).value=this.responseObj.generatedcontent;root.querySelector(this.SELECTORS.RESPONSEWRAPPER).classList.remove("hidden");root.querySelector(this.SELECTORS.RESPONSEPLACEHOLDER).classList.add("hidden")}getRequestArgs(root){return{contextid:(0,_options.getContextId)(this.editor),prompttext:root.querySelector(this.SELECTORS.PROMPTAREA()).value}}replaceLineBreaks(text){const textWithBreaks=text.replace(/\n{2,}|\r\n/g,"<br/><br/>").replace(/\n/g,"<br/>");return"<p>".concat(textWithBreaks,"</p>")}}return _exports.default=GenerateText,_exports.default}));
//# sourceMappingURL=generatetext.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -113,7 +113,7 @@ export default class GenerateBase {
* @param {Object} root The root element of the modal.
*/
hideLoadingSpinner(root) {
const loadingSpinnerDiv = root.querySelector(`#${this.editor.id}_tiny_aiplacement_spinner`);
const loadingSpinnerDiv = root.querySelector(`[id="${this.editor.id}_tiny_aiplacement_spinner"]`);
loadingSpinnerDiv.classList.add('hidden');
loadingSpinnerDiv.classList.remove('tiny-aiplacement-loading-spinner-container');
}
@ -126,10 +126,10 @@ export default class GenerateBase {
* @param {String|null} removeClass - The class to be removed from the loading spinner div, if any.
*/
async displayLoading(root, submitBtn, removeClass = null) {
const loadingSpinnerDiv = root.querySelector(`#${this.editor.id}_tiny_aiplacement_spinner`);
const overlayDiv = root.querySelector(`#${this.editor.id}_tiny_aiplacement_overlay`);
const blurDiv = root.querySelector(`#${this.editor.id}_tiny_aiplacement_blur`);
const loadingTextDiv = root.querySelector(`#${this.editor.id}_tiny_aiplacement_loading_text`);
const loadingSpinnerDiv = root.querySelector(`[id="${this.editor.id}_tiny_aiplacement_spinner"]`);
const overlayDiv = root.querySelector(`[id="${this.editor.id}_tiny_aiplacement_overlay"]`);
const blurDiv = root.querySelector(`[id="${this.editor.id}_tiny_aiplacement_blur"]`);
const loadingTextDiv = root.querySelector(`[id="${this.editor.id}_tiny_aiplacement_loading_text"]`);
const actionButtons = root.querySelectorAll('.tiny-aiplacement-generate-footer button');
loadingMessages(loadingTextDiv);
@ -157,9 +157,9 @@ export default class GenerateBase {
* @param {Object} submitBtn The submit button element.
*/
async hideLoading(root, submitBtn) {
const loadingSpinnerDiv = root.querySelector(`#${this.editor.id}_tiny_aiplacement_spinner`);
const overlayDiv = root.querySelector(`#${this.editor.id}_tiny_aiplacement_overlay`);
const blurDiv = root.querySelector(`#${this.editor.id}_tiny_aiplacement_blur`);
const loadingSpinnerDiv = root.querySelector(`[id="${this.editor.id}_tiny_aiplacement_spinner"]`);
const overlayDiv = root.querySelector(`[id="${this.editor.id}_tiny_aiplacement_overlay"]`);
const blurDiv = root.querySelector(`[id="${this.editor.id}_tiny_aiplacement_blur"]`);
const actionButtons = root.querySelectorAll('.tiny-aiplacement-generate-footer button');
if (loadingSpinnerDiv) {
loadingSpinnerDiv.classList.add('hidden');

View File

@ -31,13 +31,13 @@ import GenerateBase from 'tiny_aiplacement/generatebase';
export default class GenerateImage extends GenerateBase {
SELECTORS = {
GENERATEBUTTON: () => `#${this.editor.id}_tiny_aiplacement_generatebutton`,
PROMPTAREA: () => `#${this.editor.id}_tiny_aiplacement_imageprompt`,
IMAGECONTAINER: () => `#${this.editor.id}_tiny_aiplacement_generate_image`,
GENERATEBUTTON: () => `[id="${this.editor.id}_tiny_aiplacement_generatebutton"]`,
PROMPTAREA: () => `[id="${this.editor.id}_tiny_aiplacement_imageprompt"]`,
IMAGECONTAINER: () => `[id="${this.editor.id}_tiny_aiplacement_generate_image"]`,
GENERATEBTN: '[data-action="generate"]',
INSERTBTN: '[data-action="inserter"]',
BACKTBTN: '[data-action="back"]',
GENERATEDIMAGE: () => `#${this.editor.id}_tiny_generated_image`,
GENERATEDIMAGE: () => `[id="${this.editor.id}_tiny_generated_image"]`,
};
imageURL = null;

View File

@ -31,11 +31,11 @@ import GenerateBase from './generatebase';
export default class GenerateText extends GenerateBase {
SELECTORS = {
GENERATEBUTTON: () => `#${this.editor.id}_tiny_aiplacement_generatebutton`,
PROMPTAREA: () => `#${this.editor.id}_tiny_aiplacement_textprompt`,
GENERATEBUTTON: () => `[id="${this.editor.id}_tiny_aiplacement_generatebutton"]`,
PROMPTAREA: () => `[id="${this.editor.id}_tiny_aiplacement_textprompt"]`,
RESPONSEWRAPPER: '.tiny_aiplacement_textresponse',
RESPONSEPLACEHOLDER: '.tiny_aiplacement_textresponse_placeholder',
GENERATEDRESPONSE: () => `#${this.editor.id}_tiny_aiplacement_textresponse`,
GENERATEDRESPONSE: () => `[id="${this.editor.id}_tiny_aiplacement_textresponse"]`,
INSERTBTN: '[data-action="inserter"]',
BACKTBTN: '[data-action="back"]',
};

View File

@ -49,7 +49,7 @@ class plugininfo extends plugin implements plugin_with_buttons, plugin_with_menu
array $fpoptions,
?editor $editor = null
): bool {
return in_array(true, self::get_allowed_actions($context));
return in_array(true, self::get_allowed_actions($context, $options));
}
#[\Override]
@ -72,7 +72,7 @@ class plugininfo extends plugin implements plugin_with_buttons, plugin_with_menu
global $USER;
$userid = (int) $USER->id;
$allowedactions = self::get_allowed_actions($context);
$allowedactions = self::get_allowed_actions($context, $options);
return array_merge([
'contextid' => $context->id,
@ -85,9 +85,10 @@ class plugininfo extends plugin implements plugin_with_buttons, plugin_with_menu
* Get the allowed actions for the plugin.
*
* @param context $context The context that the editor is used within
* @param array $options The options passed in when requesting the editor
* @return array The allowed actions.
*/
private static function get_allowed_actions(context $context): array {
private static function get_allowed_actions(context $context, array $options): array {
[$plugintype, $pluginname] = explode('_', \core_component::normalize_componentname('aiplacement_editor'), 2);
$manager = \core_plugin_manager::resolve_plugininfo_class($plugintype);
$allowedactions = [];
@ -99,7 +100,14 @@ class plugininfo extends plugin implements plugin_with_buttons, plugin_with_menu
&& manager::is_action_enabled('aiplacement_editor', $action)
&& !empty($providers[$providerclass])
) {
$allowedactions[$action] = true;
if ($action == 'generate_image') {
// For generate image, we need to check if the user has the capability to upload files.
$canhavefiles = !empty($options['maxfiles']);
$canhaveexternalfiles = !empty($options['return_types']) && ($options['return_types'] & FILE_EXTERNAL);
$allowedactions[$action] = $canhavefiles || $canhaveexternalfiles;
} else {
$allowedactions[$action] = true;
}
} else {
$allowedactions[$action] = false;
}