@if (module_enabled('Aitools') && (in_array('admin', user_roles()) || user()->permission('view_aitools') == 'all')) // Add custom rephrase button to toolbar (only if Aitools module is enabled) function addRephraseButton(quillInstance, editorId) { let attempts = 0; const maxAttempts = 10; function tryAddButton() { attempts++; const editorElement = document.querySelector(editorId); if (!editorElement) { if (attempts < maxAttempts) { setTimeout(tryAddButton, 100); } return; } // Toolbar is typically a sibling of the editor container const toolbarContainer = editorElement.parentNode.querySelector('.ql-toolbar'); if (!toolbarContainer) { if (attempts < maxAttempts) { setTimeout(tryAddButton, 100); } return; } // Check if button already exists if (toolbarContainer.querySelector('.ql-rephrase')) { return; } // Create the button element const rephraseButton = document.createElement('button'); rephraseButton.type = 'button'; rephraseButton.className = 'ql-rephrase'; rephraseButton.setAttribute('title', 'Rephrase Text'); rephraseButton.setAttribute('aria-label', 'Rephrase'); rephraseButton.innerHTML = ''; // Add click handler rephraseButton.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); handleRephrase(quillInstance); }); // Find the clean button and its format container const cleanButton = toolbarContainer.querySelector('.ql-clean'); let inserted = false; if (cleanButton) { // Find the ql-formats container that holds the clean button const formatContainer = cleanButton.closest('.ql-formats'); if (formatContainer && cleanButton.parentNode) { // Add button to the same format group after clean button cleanButton.parentNode.insertBefore(rephraseButton, cleanButton.nextSibling); inserted = true; } else if (cleanButton.parentNode) { // If no format container, insert after clean button directly cleanButton.parentNode.insertBefore(rephraseButton, cleanButton.nextSibling); inserted = true; } } // If we haven't inserted the button yet, create a new format group at the end if (!inserted && !rephraseButton.parentNode) { const formatsSpan = document.createElement('span'); formatsSpan.className = 'ql-formats'; formatsSpan.appendChild(rephraseButton); toolbarContainer.appendChild(formatsSpan); inserted = true; } if (inserted && rephraseButton.parentNode) { console.log('Rephrase button added successfully to', editorId); } } // Start trying to add the button setTimeout(tryAddButton, 150); } /** * Handle rephrase button click * * @param {Quill} quillInstance */ function handleRephrase(quillInstance) { let range = quillInstance.getSelection(true); // If no selection, get all text if (!range || range.length === 0) { const text = quillInstance.getText(); if (!text || text.trim().length === 0) { showRephraseError('{{ __("aitools::messages.pleaseEnterSomeText") }}'); return; } range = { index: 0, length: text.length }; } const textToRephrase = quillInstance.getText(range.index, range.length); if (!textToRephrase || textToRephrase.trim().length === 0) { showRephraseError('{{ __("aitools::messages.pleaseEnterSomeText") }}'); return; } // Show loading state const toolbarContainer = quillInstance.container.parentNode.querySelector('.ql-toolbar'); const rephraseButton = toolbarContainer ? toolbarContainer.querySelector('.ql-rephrase') : null; if (rephraseButton) { rephraseButton.classList.add('ql-disabled'); rephraseButton.setAttribute('title', 'Rephrasing...'); } // Call API to rephrase text $.ajax({ url: "{{ route('projects.rephrase-text') }}", type: 'POST', data: { text: textToRephrase, _token: $('meta[name="csrf-token"]').attr('content') }, success: function(response) { if (response.status === 'success' && response.rephrased_text) { // Delete selected text and insert rephrased text quillInstance.deleteText(range.index, range.length, 'user'); quillInstance.insertText(range.index, response.rephrased_text, 'user'); quillInstance.setSelection(range.index + response.rephrased_text.length, 0); // Show success message if (typeof Swal !== 'undefined') { // Swal.fire({ // icon: 'success', // text: '{{ __("aitools::messages.textRephrasedSuccessfully") }}', // toast: true, // position: "top-end", // timer: 3000, // timerProgressBar: true, // showConfirmButton: false, // customClass: { // confirmButton: "btn btn-primary", // }, // showClass: { // popup: "swal2-noanimation", // backdrop: "swal2-noanimation", // }, // }); } else if (typeof showSuccessMessage !== 'undefined') { showSuccessMessage('{{ __("aitools::messages.textRephrasedSuccessfully") }}'); } } else { showRephraseError(response.message || '{{ __("aitools::messages.aiRequestFailed") }}'); } }, error: function(xhr) { let errorMessage = '{{ __("aitools::messages.aiRequestFailed") }}'; if (xhr.responseJSON && xhr.responseJSON.message) { errorMessage = xhr.responseJSON.message; } else if (xhr.responseJSON && xhr.responseJSON.error) { errorMessage = xhr.responseJSON.error; } showRephraseError(errorMessage); }, complete: function() { // Remove loading state const toolbarContainer = quillInstance.container.parentNode.querySelector('.ql-toolbar'); const rephraseBtn = toolbarContainer ? toolbarContainer.querySelector('.ql-rephrase') : null; if (rephraseBtn) { rephraseBtn.classList.remove('ql-disabled'); rephraseBtn.setAttribute('title', '{{ __("aitools::messages.rephraseText") }}'); } } }); } /** * Show rephrase error message * * @param {string} message */ function showRephraseError(message) { if (typeof Swal !== 'undefined') { Swal.fire({ icon: 'error', text: message, showConfirmButton: true, customClass: { confirmButton: 'btn btn-primary', }, showClass: { popup: 'swal2-noanimation', backdrop: 'swal2-noanimation' }, buttonsStyling: false }); } else if (typeof showAlertMessage !== 'undefined') { showAlertMessage(message, 'error'); } else if (typeof toastr !== 'undefined') { toastr.error(message); } else { alert(message); } } @endif