Файл: ${file.name} (тип: ${file.mimetype})
`; } resultAnswer.innerHTML += element; }); } requestTitle.innerHTML = '${app.btn_main_action}
/); const language = languageMatch ? languageMatch[1] : 'plaintext'; return result.replace(//g, ``); } catch (err) { } return markdownString; } let configThisItem = null; function addTextToVoiceToForm(element) { configThisItem = element; const textToVoiceSpeechesTemplate = document.getElementById('text-to-voice'); const textToVoiceSpeechesTemplateToForm = document.importNode(textToVoiceSpeechesTemplate.content, true); formAppFirstQuestion.appendChild(textToVoiceSpeechesTemplateToForm); const button = document.querySelector('.add-new-speech'); button.addEventListener('click', addNewSpeech); initArrowUpDownSpeaches(); loadSpeechesFromLocalStorage(); } function addNewSpeech() { const textToVoiceSpeechTemplate = document.getElementById('text-to-voice-speeches'); const textToVoiceSpeechTemplateToForm = document.importNode(textToVoiceSpeechTemplate.content, true); const speechesBlock = document.querySelector('#speeches'); const uniqueSpeechId = generateUniqueId(); if (configThisItem.inputTypeFiles) { const speechVideoBlock = textToVoiceSpeechTemplateToForm.querySelector('.video-upload'); speechVideoBlock.style.display = 'block'; const speechVideoInput = speechVideoBlock.querySelector('.video-input'); speechVideoInput.accept = configThisItem.inputTypeFiles; speechVideoInput.addEventListener('change', function(event) { const currentSpeechItem = speechVideoInput.closest('.speech-item'); const videoPreview = currentSpeechItem.querySelector('.video-preview'); const describeVideo = currentSpeechItem.querySelector('.describe-video'); const file = event.target.files[0]; if (file) { videoPreview.src = URL.createObjectURL(file); videoPreview.style.display = 'block'; describeVideo.style.display = 'block'; } const createSpeechFromFile = currentSpeechItem.querySelector('.create-speech-from-file'); const promptSpeechFromFile = currentSpeechItem.querySelector('.describe-file'); const promptSpeechTextToVoice = currentSpeechItem.querySelector('.text-to-voice'); promptSpeechFromFile.focus(); createSpeechFromFile.addEventListener('click', async function (event) { event.preventDefault(); const lang = currentSpeechItem.querySelector('select[name="lang[]"]'); if (!lang.value) { toastr.warning('Lang must be required'); promptSpeechFromFile.focus(); return; } let prompt = promptSpeechFromFile.value; if (!prompt) { toastr.warning('Prompt must be required'); promptSpeechFromFile.focus(); return; } createSpeechFromFile.innerText = 'Please wait.'; createSpeechFromFile.style.color = 'black'; createSpeechFromFile.disabled = true; let url = 'https://aisearch.tech/api/v3/app/any-task/execute'; const formData = new FormData(); formData.append('stream', true); formData.append('user-prompt_files', file); formData.append('user-prompt', prompt); formData.append('opt_select_lang', lang.value); fetch(url, { method: 'POST', body: formData, headers: { 'enctype': 'multipart/form-data' } }).then(response => { if (!response.ok) { return response.json().then(errorData => { throw new Error(`${errorData.message}`); }); } const reader = response.body.getReader(); const decoder = new TextDecoder('utf-8'); const processChunk = async () => { const {done, value } = await reader.read(); if (done) { toastr.success('Task accomplished'); Alpine.store('appLoadingIndicator').hide(); createSpeechFromFile.innerText = 'Redo it.'; createSpeechFromFile.style.color = 'black'; createSpeechFromFile.disabled = false; return; } const chunk = decoder.decode(value, { stream: true }); const messages = chunk.split('\n').filter(line => line); messages.forEach(message => { try { const jsonData = JSON.parse(message.replace(/^data: /, '')); if (jsonData.type === 'start') { } if (jsonData.type === 'search_result') { if (jsonData.data.result.organic.length > 0) { } } if (jsonData.type === 'data') { promptSpeechTextToVoice.value += jsonData.data; } if (jsonData.type === 'stop') { } } catch (e) { } }); await processChunk(); }; processChunk(); }).catch(error => { toastr.warning(error.message); createSpeechFromFile.innerText = 'Repeat.'; createSpeechFromFile.style.color = 'black'; createSpeechFromFile.disabled = false; }); }); }); if ( navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia ) { const speechVideoScreenRecord = speechVideoBlock.querySelector('.video-screen-record'); speechVideoScreenRecord.style.display = 'block'; speechVideoScreenRecord.addEventListener('click', function(event) { let mediaRecorder; let chunks = []; if (mediaRecorder && mediaRecorder.state === "recording") { mediaRecorder.stop(); toastr.success('Recording stopped'); return; } if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) { navigator.mediaDevices.getDisplayMedia({ video: true }) .then(stream => { mediaRecorder = new MediaRecorder(stream); mediaRecorder.ondataavailable = event => { chunks.push(event.data); }; mediaRecorder.onstop = () => { const blob = new Blob(chunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = 'screen-recording.webm'; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); const file = new File([blob], 'screen-recording.webm', { type: 'video/webm' }); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); speechVideoInput.files = dataTransfer.files; const event = new Event('change', { bubbles: true }); speechVideoInput.dispatchEvent(event); chunks = []; }; mediaRecorder.start(); toastr.success('Recording has started'); }) .catch(err => { toastr.error('Screen Access Error'); console.error("Screen Access Error: ", err); }); } else { console.log("Sorry, your browser does not support screen recording."); } }); } } const speechIdInput = textToVoiceSpeechTemplateToForm.querySelector('.speech-id'); if (speechIdInput) { speechIdInput.value = uniqueSpeechId; } const buttonsPreviewSpeech = textToVoiceSpeechTemplateToForm.querySelector('.preview-speech'); const buttonsDeleteSpeech = textToVoiceSpeechTemplateToForm.querySelector('.delete-speech'); const buttonsVoiceExample = textToVoiceSpeechTemplateToForm.querySelector('.voice-example'); loadTextToVoiceDict(textToVoiceSpeechTemplateToForm); speechesBlock.appendChild(textToVoiceSpeechTemplateToForm); initArrowUpDownSpeaches(); saveSpeechesToLocalStorage(); buttonsDeleteSpeech.addEventListener('click', function() { const speechItem = buttonsDeleteSpeech.closest('.speech-item'); if (speechItem) { speechItem.remove(); saveSpeechesToLocalStorage(); } }); buttonsVoiceExample.addEventListener('click', function() { const speechItem = buttonsVoiceExample.closest('.speech-item'); const selectElement = speechItem.querySelector('select[name="speakers[]"]'); const selectedValue = selectElement ? selectElement.value : null; let routeExample = 'https://aisearch.tech/api/v3/app/directory/text-to-voice/examples/download/__voiceId__'; routeExample = routeExample.replace('__voiceId__', selectedValue); if (selectedValue) { fetch(routeExample) .then(response => { if (response.ok) { return response.blob(); } throw new Error('Network error'); }) .then(blob => { const url = URL.createObjectURL(blob); const audio = new Audio(url); audio.play(); }) .catch(error => { toastr.error('This speaker's sample file was not found, we are already aware of this and will fix it soon.:', error); }); } else { toastr.warning('Please select speaker'); selectElement.focus(); } }); buttonsPreviewSpeech.addEventListener('click', function() { previewSpeechRun(buttonsPreviewSpeech); }); const textAreas = document.querySelectorAll('textarea[name="text-to-voice[]"]'); textAreas.forEach(textArea => { const uploadButton = document.createElement('button'); uploadButton.innerHTML = ``; uploadButton.style.marginTop = '-40px'; uploadButton.style.position = 'absolute'; uploadButton.style.right = '0'; uploadButton.type = 'button'; uploadButton.addEventListener('click', () => { const inputFile = document.createElement('input'); inputFile.type = 'file'; inputFile.accept = '.txt, .doc, .docx'; inputFile.addEventListener('change', handleFileSelectToTextArea(textArea)); inputFile.click(); return; }); textArea.parentNode.append(uploadButton); }); trackFormChanges('app_form'); return buttonsDeleteSpeech.closest('.speech-item'); } function previewSpeechRun(buttonsPreviewSpeech = null) { if (buttonsPreviewSpeech === null) { return; } let partiallyTaskUuid = document.getElementById('partiallyTaskUuid').value; const currentSpeechItem = buttonsPreviewSpeech.closest('.speech-item'); const speechesBlock = buttonsPreviewSpeech.closest('#speeches'); const speechItems = speechesBlock.querySelectorAll('.speech-item'); const currentSpeechId = currentSpeechItem.querySelector('.speech-id').value; const validClientData = { speechIds: {}, }; if (currentSpeechId) { validClientData['speechId'] = currentSpeechId; } if (partiallyTaskUuid !== '') { validClientData['partiallyTaskUuid'] = partiallyTaskUuid; } speechItems.forEach(item => { let textToVoice = item.querySelector('textarea[name="text-to-voice[]"]'); let voiceId = item.querySelector('select[name="speakers[]"]'); let lang = item.querySelector('select[name="lang[]"]'); let speechId = item.querySelector('input[name="speechId[]"]'); let fileVideoToVoiceOver = item.querySelector('input[name="fileVideoToVoice[]"]').files[0]; validClientData.speechIds[speechId.value] = { lang: lang.value, speaker: voiceId.value, 'text-to-voice': textToVoice.value, 'fileVideoToVoice': fileVideoToVoiceOver }; }); const formData = new FormData(); formData.append('partiallyTaskUuid', validClientData.partiallyTaskUuid); formData.append('speechId', validClientData.speechId); for (const [key, value] of Object.entries(validClientData.speechIds)) { formData.append(`speechIds[${key}][lang]`, value.lang); formData.append(`speechIds[${key}][speaker]`, value.speaker); formData.append(`speechIds[${key}][text-to-voice]`, value['text-to-voice']); if (value['fileVideoToVoice']) { formData.append(`speechIds[${key}][fileVideoToVoice]`, value['fileVideoToVoice']); } } let url = 'https://aisearch.tech/api/v3/app/_rewrite_/execute'; url = url.replace('_rewrite_', activeAppConfig.slug); startPreviewSpeechItem(buttonsPreviewSpeech); fetch(url, { method: 'POST', headers: { 'enctype': 'multipart/form-data' }, body: formData }) .then(response => response.json()) .then(async data => { if (!data.result) { toastr.error(data.message); finishPreviewSpeechItem(buttonsPreviewSpeech); } if (data.result) { const taskUuid = data.uuid; document.getElementById('partiallyTaskUuid').value = taskUuid; addParamToUrlSilent('formLoadTaskBYUuid', taskUuid); await getResultPreviewSpeech(taskUuid, buttonsPreviewSpeech); } finishPreviewSpeechItem(buttonsPreviewSpeech); }) .catch((error) => { toastr.error(error); finishPreviewSpeechItem(buttonsPreviewSpeech); }); } async function getResultPreviewSpeech(taskUuid = null, buttonsPreviewSpeech = null) { let checkUrl = 'https://aisearch.tech/api/v3/app/task/__uuid__/result'; checkUrl = checkUrl.replace('__uuid__', taskUuid); let hasProcessed = false; const intervalId = setInterval(async () => { try { const response = await fetch(checkUrl); const result = await response.json(); if (result.result) { let status = result.data.status; if ( status === 2 || 4 ) { hasProcessed = true; clearInterval(intervalId); loadDataToFormTextToVoice(result, buttonsPreviewSpeech); Alpine.store('appLoadingIndicator').hide(); } if (status === 3) { hasProcessed = true; clearInterval(intervalId); Alpine.store('appLoadingIndicator').hide(); toastr.error('The task failed with an error'); } } else { toastr.error('Error checking task status.'); clearInterval(intervalId); Alpine.store('appLoadingIndicator').hide(); } } catch (error) { toastr.error('Error sending GET request to check status:' + error); Alpine.store('appLoadingIndicator').hide(); } }, 500); } function loadDataToFormTextToVoice(result, buttonsPreviewSpeech = null) { let task = result.data; let out = result.data.output.speechIds; let speechId = null; if (buttonsPreviewSpeech) { const speechItem = buttonsPreviewSpeech.closest('.speech-item'); speechId = speechItem.querySelector('.speech-id').value; let speechIdNewFile = null; if ((speechIdNewFile = out[speechId]['file']['name'])) { let routeDownload = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; routeDownload = routeDownload.replace('__uuid__', task.uuid); if (out[speechId]['fileVideo']['name']) { let routeDownloadVideo = routeDownload.replace('__name__', out[speechId]['fileVideo']['name']); const speechItemDataVideo = speechItem.querySelector('.video-output'); speechItemDataVideo.style.display = 'block'; const speechItemDataVideoPreviewSpeech = speechItem.querySelector('.video-preview-speech'); speechItemDataVideoPreviewSpeech.src = routeDownloadVideo; } routeDownload = routeDownload.replace('__name__', speechIdNewFile); const speechItemDataAudio = speechItem.querySelector('.data-audio'); speechItemDataAudio.setAttribute('data-audio', routeDownload); speechItemDataAudio.style.visibility = 'visible'; generateWaveForm(speechItemDataAudio) } return; } for (let key in out) { if (out.hasOwnProperty(key)) { let speechItem = addNewSpeech(); const speechItemTextToVoice = speechItem.querySelector('.text-to-voice'); speechItemTextToVoice.value = out[key]['text-to-voice']; const speechItemId = speechItem.querySelector('.speech-id'); speechItemId.value = key; const selectSpeakers = speechItem.querySelector('select[name="speakers[]"]'); if (out[key]['voice_id']) { const optionExists = Array.from(selectSpeakers.options).some(option => option.value === out[key]['voice_id']); if (optionExists) { selectSpeakers.value = out[key]['voice_id']; } } if (out[key]['file']['name']) { let routeDownload = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; routeDownload = routeDownload.replace('__uuid__', task.uuid); if (out[key]['fileVideo']['name']) { let routeDownloadVideo = routeDownload.replace('__name__', out[key]['fileVideo']['name']); const speechItemDataVideo = speechItem.querySelector('.video-output'); speechItemDataVideo.style.display = 'block'; const speechItemDataVideoPreviewSpeech = speechItem.querySelector('.video-preview-speech'); speechItemDataVideoPreviewSpeech.src = routeDownloadVideo; } routeDownload = routeDownload.replace('__name__', out[key]['file']['name']); const speechItemDataAudio = speechItem.querySelector('.data-audio'); speechItemDataAudio.setAttribute('data-audio', routeDownload); speechItemDataAudio.style.visibility = 'visible'; generateWaveForm(speechItemDataAudio) } } } } function handleFileSelectToTextArea(textArea) { return function(event) { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (e) => { const contents = e.target.result; if (file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' || file.type === 'application/msword') { mammoth.convertToHtml({arrayBuffer: contents}) .then(function(result) { if (result.value) { textArea.value = result.value; } else { toastr.error('The file is empty or contains invalid content..'); } }) .catch(function(err) { toastr.error('Error during conversion: ' + err.message); }); } else { try { const textContent = new TextDecoder().decode(contents); textArea.value = textContent; } catch (error) { toastr.error('Error reading text content: ' + error.message); } } calculateData(); }; reader.readAsArrayBuffer(file); }; } function generateWaveForm(el) { let audioUrl = el.getAttribute( 'data-audio' ); let container = el.querySelector( '.audio-preview' ); let playButton = el.querySelector( 'button' ); let timeData = el.querySelector( 'span' ); let volumeControl = el.querySelector( '#volume' ); let downloadButton = el.querySelector( '.download-button' ); if ( !audioUrl || audioUrl === '' ) { return; } if (el.waveform) { el.waveform.destroy(); } while ( container.firstElementChild ) { container.firstElementChild.remove(); } let waveform = WaveSurfer.create( { container: container, waveColor: '#bcbac8', progressColor: '#320580', cursorWidth: 0, barWidth: 1, interact: true, autoCenter: false, hideScrollbar: true, height: 22, }); el.waveform = waveform; waveform.load( audioUrl ); waveform.on( 'ready', function () { let duration = waveform.getDuration(); timeData.textContent = formatTime( duration ); downloadButton.href = audioUrl; } ); waveform.on( 'audioprocess', function () { let currentTime = waveform.getCurrentTime(); timeData.textContent = formatTime( currentTime ); } ); waveform.on( 'play', function () { playButton.classList.add( 'is-playing' ); } ); waveform.on( 'pause', function () { playButton.classList.remove( 'is-playing' ); } ); playButton.addEventListener( 'click', function () { waveform.playPause(); } ); volumeControl.addEventListener('input', function() { waveform.setVolume(this.value / 100); }); } async function loadTextToVoiceDict(speechItem = null) { if (speechItem === null) { return; } const speechItemOptions = speechItem.querySelector('.text-to-voice-options'); const oneHour = 60 * 60 * 1000; const currentTime = Date.now(); let textToVoiceDict = localStorage.getItem('textToVoiceDict'); let lastUpdated = localStorage.getItem('textToVoiceDictLastUpdated'); if (textToVoiceDict) { try { textToVoiceDict = JSON.parse(textToVoiceDict); lastUpdated = JSON.parse(lastUpdated); if (currentTime - lastUpdated > oneHour) { textToVoiceDict = null; localStorage.removeItem('textToVoiceDictLastUpdated'); localStorage.removeItem('textToVoiceDict'); } } catch (error) { localStorage.removeItem('textToVoiceDict'); localStorage.removeItem('textToVoiceDictLastUpdated'); textToVoiceDict = null; } } if (!textToVoiceDict) { try { const url = 'https://aisearch.tech/api/v3/app/directory/text-to-voice'; const response = await fetch(url); if (!response.ok) { throw new Error(`Ошибка: ${response.status}`); } const data = await response.json(); localStorage.setItem('textToVoiceDict', JSON.stringify(data)); localStorage.setItem('textToVoiceDictLastUpdated', JSON.stringify(currentTime)); textToVoiceDict = data; } catch (error) { toastr.error('Error loading data:', error); } } populateLanguageOptions(textToVoiceDict.data.languages, speechItemOptions); populateGenderOptions(textToVoiceDict.data.gender, speechItemOptions); populateSpeechOptions(textToVoiceDict.data.speakers, speechItemOptions); populateEmotionOptions([], speechItemOptions) } function loadSpeechesFromLocalStorage() { const formLoadTaskBYUuid = getParameterByName('formLoadTaskBYUuid'); if (!formLoadTaskBYUuid) { addNewSpeech(); return; } getResultPreviewSpeech(formLoadTaskBYUuid); } function obtainTextToVoiceDict() { let textToVoiceDict = localStorage.getItem('textToVoiceDict'); if (!textToVoiceDict) { fetch('https://aisearch.tech/api/v3/app/directory/text-to-voice') .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { textToVoiceDict = JSON.stringify(data); localStorage.setItem('textToVoiceDict', JSON.stringify(data)); }) .catch(error => { toastr.error('There was a problem with the fetch operation:', error); }); } else { textToVoiceDict = JSON.parse(textToVoiceDict); const parsedData = textToVoiceDict; const lastUpdate = new Date(parsedData.last_update); const now = new Date(); const fiveMinutes = 5 * 60 * 1000; if (now - lastUpdate > fiveMinutes) { fetch('https://aisearch.tech/api/v3/app/directory/text-to-voice') .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { localStorage.setItem('textToVoiceDict', JSON.stringify(data)); }) .catch(error => { toastr.error('There was a problem with the fetch operation:', error); }); } else { } } return textToVoiceDict; } function filteredSpeakers(speechItem = null) { if (speechItem === null) { return; } const selectSpeakers = speechItem.querySelector('select[name="speakers[]"]'); if (!selectSpeakers) { return; } selectSpeakers.innerHTML = ''; selectSpeakers.name = 'speakers[]'; const langSelect = speechItem.querySelector('select[name="lang[]"]'); const genderSelect = speechItem.querySelector('select[name="gender[]"]'); if (!langSelect) { toastr.error('Element named lang not found.'); } if (!genderSelect) { toastr.error('Element named gender not found.'); } const textToVoiceDict = obtainTextToVoiceDict(); const selectGender = genderSelect.value; const selectedLang = langSelect.value; const speakers = textToVoiceDict.data.speakers; let filteredGender = true; if (selectGender === 'all') { filteredGender = false; } for (const speaker of speakers) { if ( inArray(selectedLang, speaker.lang) && (!filteredGender || selectGender === speaker.gender) ) { const option = document.createElement('option'); option.value = speaker.speaker_id; option.textContent = speaker.speaker_name + ' (' + speaker.gender + ')'; if (speaker.accent) { option.textContent += ' (' + speaker.accent + ')'; } selectSpeakers.appendChild(option); } } } function filteredVoiceEmotion(speechItem = null) { if (speechItem === null) { return; } const selectSpeakers = speechItem.querySelector('select[name="speakers[]"]'); if (!selectSpeakers) { return; } const speakerSelect = speechItem.querySelector('select[name="speakers[]"]'); const textToVoiceDict = obtainTextToVoiceDict(); const speakers = textToVoiceDict.data.speakers; const emotionSelect = speechItem.querySelector('select[name="emotion[]"]'); emotionSelect.style.display = 'none'; for (const speaker of speakers) { if (speaker.speaker_id === speakerSelect.value && speaker.emotion.length > 0) { emotionSelect.style.display = 'block'; for (const [code, name] of Object.entries(speaker.emotion)) { const option = document.createElement('option'); option.value = name; option.textContent = name; emotionSelect.appendChild(option); } } } } function populateSpeechOptions(speakers, speechItem) { if (speechItem.querySelector('select[name="speakers"]')) { return; } const select = document.createElement('select'); select.classList = 'cursor-pointer lqd-input block peer w-full px-4 py-2 border border-input-border text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring dark:focus:ring-foreground/10 sm:text-2xs lqd-input-lg h-11 rounded-xl bg-background text-heading-foreground focus:ring-heading-foreground/5'; select.name = 'speakers[]'; for (const [id, data] of Object.entries(speakers)) { const option = document.createElement('option'); option.value = data.speaker_id; option.textContent = data.speaker_name; if (data.gender) { option.textContent += ' (' + data.gender + ')'; } if (data.accent) { option.textContent += ' (' + data.accent + ')'; } select.appendChild(option); } select.addEventListener('change', function () { const speechItem = select.closest('.speech-item'); filteredVoiceEmotion(speechItem); }); const spanBlock = document.createElement('span'); spanBlock.classList = 'mr-2 text-lg float-left'; spanBlock.appendChild(select); speechItem.appendChild(spanBlock) } function populateLanguageOptions(languages, speechItem) { if (speechItem.querySelector('select[name="lang"]')) { return; } const select = document.createElement('select'); select.classList = 'cursor-pointer lqd-input block peer w-full px-4 py-2 border border-input-border text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring dark:focus:ring-foreground/10 sm:text-2xs lqd-input-lg h-11 rounded-xl bg-background text-heading-foreground focus:ring-heading-foreground/5'; select.name = 'lang[]'; for (const [code, name] of Object.entries(languages)) { const option = document.createElement('option'); option.value = code; option.textContent = name; if (code === 'ru') { option.selected = true; } select.appendChild(option); } const spanBlock = document.createElement('span'); spanBlock.classList = 'mr-2 text-lg float-left'; spanBlock.appendChild(select); speechItem.appendChild(spanBlock); select.addEventListener('change', function () { const speechItem = select.closest('.speech-item'); filteredSpeakers(speechItem); }); } function populateGenderOptions(gender, speechItem) { const select = document.createElement('select'); select.classList = 'cursor-pointer lqd-input block peer w-full px-4 py-2 border border-input-border text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring dark:focus:ring-foreground/10 sm:text-2xs lqd-input-lg h-11 rounded-xl bg-background text-heading-foreground focus:ring-heading-foreground/5'; select.name = 'gender[]'; const option = document.createElement('option'); option.value = 'all'; option.selected = true; option.textContent = 'Gender: all'; select.appendChild(option); for (const [code, name] of Object.entries(gender)) { if (name !== 'non-binary') { const option = document.createElement('option'); option.value = name; option.textContent = name; select.appendChild(option); } } select.addEventListener('change', function () { const speechItem = select.closest('.speech-item'); filteredSpeakers(speechItem); }); const spanBlock = document.createElement('span'); spanBlock.classList = 'mr-2 text-lg float-left'; spanBlock.appendChild(select); speechItem.appendChild(spanBlock) } function populateEmotionOptions(emotion, speechItem) { const select = document.createElement('select'); select.classList = 'cursor-pointer lqd-input block peer w-full px-4 py-2 border border-input-border text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring dark:focus:ring-foreground/10 sm:text-2xs lqd-input-lg h-11 rounded-xl bg-background text-heading-foreground focus:ring-heading-foreground/5'; select.name = 'emotion[]'; select.style.display = "none"; const option = document.createElement('option'); option.value = null; option.textContent = 'none'; select.appendChild(option); const spanBlock = document.createElement('span'); spanBlock.classList = 'mr-2 text-lg float-left'; spanBlock.appendChild(select); speechItem.appendChild(spanBlock) } function initArrowUpDownSpeaches() { document.querySelectorAll('.speech-item.mb-3').forEach((speech) => { const existingUpButton = speech.querySelector('.up-btn'); const existingDownButton = speech.querySelector('.down-btn'); if (existingUpButton) speech.removeChild(existingUpButton); if (existingDownButton) speech.removeChild(existingDownButton); const upButton = document.createElement('button'); upButton.className = 'up-btn'; upButton.style.margin = '10px'; upButton.innerHTML = ' '; upButton.type = 'button'; upButton.addEventListener('click', () => { const prev = speech.previousElementSibling; if (prev) { speech.parentNode.insertBefore(speech, prev); } arrowMoveState(); }); const downButton = document.createElement('button'); downButton.className = 'down-btn'; upButton.style.margin = '10px'; downButton.innerHTML = ' '; downButton.type = 'button'; downButton.addEventListener('click', () => { const next = speech.nextElementSibling; if (next) { speech.parentNode.insertBefore(next, speech); } arrowMoveState(); }); speech.appendChild(upButton); speech.appendChild(downButton); }); } function startPreviewSpeechItem(buttonsPreviewSpeech = null) { Alpine.store('appLoadingIndicator').show(); if (buttonsPreviewSpeech === null) { return; } const initPreviewButton = buttonsPreviewSpeech.querySelector('.init-preview-button'); const loadPreviewButton = buttonsPreviewSpeech.querySelector('.load-preview-button'); if (initPreviewButton) { initPreviewButton.classList.add('hidden'); } if (loadPreviewButton) { loadPreviewButton.classList.remove('hidden'); } } function finishPreviewSpeechItem(buttonsPreviewSpeech = null) { Alpine.store('appLoadingIndicator').hide(); if (buttonsPreviewSpeech === null) { return; } const initPreviewButton = buttonsPreviewSpeech.querySelector('.init-preview-button'); const loadPreviewButton = buttonsPreviewSpeech.querySelector('.load-preview-button'); if (initPreviewButton) { initPreviewButton.classList.remove('hidden'); } if (loadPreviewButton) { loadPreviewButton.classList.add('hidden'); } } function saveSpeechesToLocalStorage() { const speechesBlock = document.querySelector('#speeches'); const speeches = Array.from(speechesBlock.children).map(item => { const inputs = item.querySelectorAll('input, textarea, select'); const speechData = {}; inputs.forEach(input => { speechData[input.name] = input.value; }); return speechData; }); localStorage.setItem('speeches', JSON.stringify(speeches)); } function formatTime( time ) { var minutes = Math.floor( time / 60 ); var seconds = Math.floor( time % 60 ); return minutes + ':' + ( seconds < 10 ? '0' : '' ) + seconds; } function addParamToUrlSilent(name, value) { const urlParams = new URLSearchParams(window.location.search); urlParams.set(name, value); let newUrl = window.location.pathname + '?' + urlParams.toString(); if (newUrl.length > 2000) { newUrl = newUrl.substring(0, 2000); } window.history.replaceState({ path: newUrl }, '', newUrl); } function addExcelViewerToForm() { const excelViewerTemplate = document.getElementById('excel-viewer'); const excelViewer = document.importNode(excelViewerTemplate.content, true); formAppFirstQuestion.appendChild(excelViewer); document.querySelector('.excel-viewer').addEventListener('change', handleFileSelect); const storedFile = localStorage.getItem('selectedFile'); if (storedFile) { const fileInput = document.getElementById('file-input'); const blob = new Blob([new Uint8Array(JSON.parse(storedFile))], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); const file = new File([blob], localStorage.getItem('savedFileName') ?? 'temp_name.xlsx'); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); fileInput.files = dataTransfer.files; excelReader(file); } } window.createForm = createForm; window.selectAppButton = selectAppButton; window.formAlreadyCreated = formAlreadyCreated; function initCodeHighLight(resultBlock) { const codeElement = resultBlock.querySelector('code'); if (codeElement) { if (codeElement.hasAttribute('data-ace-initialized')) { return; } var bodyClass = document.body.className; var theme = bodyClass.includes('theme-light') ? "ace/theme/github_light_default" : "ace/theme/nord_dark"; const codeText = codeElement.textContent; const editorDiv = document.createElement('div'); editorDiv.id = `editor_${resultBlock.id}`; editorDiv.innerHTML = codeText; codeElement.appendChild(editorDiv); ace.edit(`editor_${resultBlock.id}`, { theme: theme, mode: "ace/mode/javascript", maxLines: 100, wrap: true, autoScrollEditorIntoView: true }); } } function updateEditorTheme() { var bodyClass = document.body.className; var theme = bodyClass.includes('theme-light') ? "ace/theme/github_light_default" : "ace/theme/nord_dark"; } document.querySelector('.lqd-light-dark-switch').addEventListener('click', function() { updateEditorTheme(); }); function generateUniqueId() { const existingIds = new Set([...document.querySelectorAll('[id]')].map(element => element.id)); let newId; do { newId = 'id-' + Math.random().toString(36).substr(2, 9); } while (existingIds.has(newId)); return newId; } }; function addButtonAppNotUsedYet(id) { const existingButtons = document.querySelectorAll('.app_btn_not_use_yet'); existingButtons.forEach(button => button.remove()); if (!recommendationAppsConfigs) { return; } recommendationAppsConfigs.data.forEach(app => { if (id == app.id || id == app.slug) { const element = document.getElementById('app_btn_' + app.slug); if (element) { element.remove(); } const button = document.createElement('button'); button.textContent = app.title; button.style.margin = '5px'; button.id = 'app_btn_' + app.slug; button.classList = "app_btn_not_use_yet app_btn lqd-btn group inline-flex items-center justify-center gap-1.5 text-xs font-medium rounded-full transition-all hover:-translate-y-0.5 hover:shadow-xl hover:shadow-black/5 [&[disabled]]:bg-foreground [&[disabled]]:opacity-30 [&[disabled]]:pointer-events-none lqd-btn-ghost-shadow bg-background text-foreground shadow-xs hover:bg-primary hover:text-primary-foreground dark:hover:bg-foreground dark:hover:text-background focus-visible:bg-primary focus-visible:text-primary-foreground dark:bg-foreground/[3%] dark:focus-visible:bg-foreground dark:focus-visible:text-background lqd-btn-md py-2 px-4 lqd-btn-hover-none"; button.onclick = () => { selectAppButton(app.slug); createForm(app); }; recommendedButtonsApps.prepend(button); selectAppButton(app.slug); localStorage.setItem('initConfigIdOrSlug', app.slug); if (!formAlreadyCreated) { createForm(app); } } }); } function handleFileSelect(event) { const file = event.target.files[0]; if (!file) { return; } if (file) { localStorage.setItem('savedFileName', file.name); const reader = new FileReader(); reader.onload = function (e) { const arrayBuffer = new Uint8Array(e.target.result); localStorage.setItem('selectedFile', JSON.stringify([...arrayBuffer])); localStorage.setItem('savedFileName', file.name); }; excelReader(file); } excelReader(file); } function excelReader(file) { if (file) { const reader = new FileReader(); reader.onload = function (e) { const arrayBuffer = new Uint8Array(e.target.result); localStorage.setItem('selectedFile', JSON.stringify([...arrayBuffer])); }; reader.readAsArrayBuffer(file); } const reader = new FileReader(); reader.onload = function(e) { const data = new Uint8Array(e.target.result); const workbook = XLSX.read(data, { type: 'array' }); const firstSheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[firstSheetName]; const rows = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); const firstRow = rows[0]; const secondRow = rows[1]; displayTable(firstRow, secondRow); }; reader.readAsArrayBuffer(file); } let lastInsertNewPrompt = null; function displayTable(firstRow, secondRow) { const tableContainer = document.getElementById('table-container'); tableContainer.innerHTML = ''; const table = document.createElement('table'); table.style.width = '100%'; table.id = 'excel-structure-table'; const headerRow = document.createElement('tr'); headerRow.innerHTML = '#First contentWhat to do?'; table.appendChild(headerRow); firstRow.forEach((columnName, index) => { if (columnName) { const row = document.createElement('tr'); const letter = String.fromCharCode(65 + index); const secondRowData = secondRow[index] || ''; const truncatedSecondRow = secondRowData.length > 100 ? secondRowData.slice(0, 100) + '...' : secondRowData; row.innerHTML = ` ${index + 1}${columnName} If you click on me, I will be added to the prompt tag of my column.. ${truncatedSecondRow}`; table.appendChild(row); const addButton = row.querySelector('.add-row'); addButton.addEventListener('click', function() { const newRow = document.createElement('tr'); const newIndex = table.rows.length - 1; const newLetter = String.fromCharCode(65 + newIndex); let storeValue = localStorage.getItem('excel_columns['+(newIndex + 1)+'][new]'); newRow.innerHTML = ` ${newIndex + 1} `; table.insertBefore(newRow, row.nextSibling); updateIndexes(); const deleteButton = newRow.querySelector('.delete-row'); deleteButton.addEventListener('click', function() { newRow.remove(); updateIndexes(); return; }); }); row.id = index + 1; row.addEventListener('click', function() { if (lastInsertNewPrompt) { lastInsertNewPrompt.value += ' **cell:'+row.id+'** '; lastInsertNewPrompt.focus(); } }); } }); function updateIndexes() { for(let i = 1; i < table.rows.length; i++) { table.rows[i].cells[1].innerText = i; table.rows[i].id = i; const currentTextareas = table.rows[i].getElementsByClassName('column_current'); for (let textarea of currentTextareas) { textarea.name = `columns[${i}][current]`; textarea.addEventListener('click', function() { if (lastInsertNewPrompt) { lastInsertNewPrompt = null; } }); } const newTextareas = table.rows[i].getElementsByClassName('column_new'); for (let textarea of newTextareas) { textarea.name = `columns[${i}][new]`; textarea.addEventListener('input', function() { lastInsertNewPrompt = textarea; localStorage.setItem('excel_' + textarea.name, textarea.value); }); textarea.addEventListener('click', function() { lastInsertNewPrompt = textarea; localStorage.setItem('excel_' + textarea.name, textarea.value); }) } const newHeaderInput = table.rows[i].getElementsByClassName('header_new'); for (let input of newHeaderInput) { input.name = `headers[${i}][new]`; } } } tableContainer.appendChild(table); } function exportTaskTo(elm = null, type = 'clipboard') { const getParentBlock = elm.closest('.chat-content-container'); const getResultContent = getParentBlock.querySelector('.result_answer'); let content = getResultContent.innerHTML; let tempElement = ''; switch (type) { case 'clipboard': tempElement = document.createElement('div'); tempElement.innerHTML = content; document.body.appendChild(tempElement); const selection = window.getSelection(); const range = document.createRange(); range.selectNodeContents(tempElement); selection.removeAllRanges(); selection.addRange(range); const successful = document.execCommand('copy'); if (successful) { toastr.success('Content copied to clipboard'); } else { toastr.error('Could not copy text'); } document.body.removeChild(tempElement); break; case 'pdf': downloadPDF(content); break; case 'html': const htmlBlob = new Blob([content], { type: 'text/html' }); const htmlLink = document.createElement('a'); htmlLink.href = URL.createObjectURL(htmlBlob); htmlLink.download = 'content.html'; htmlLink.click(); break; case 'word': const wordBlob = new Blob(['\ufeff', '', '', '', content, '' ], { type: 'application/msword' }); const wordLink = document.createElement('a'); wordLink.href = URL.createObjectURL(wordBlob); wordLink.download = 'content.doc'; document.body.appendChild(wordLink); wordLink.click(); document.body.removeChild(wordLink); break; case 'txt': content = getResultContent.innerText; const txtBlob = new Blob([content], { type: 'text/plain' }); const txtLink = document.createElement('a'); txtLink.href = URL.createObjectURL(txtBlob); txtLink.download = 'content.txt'; document.body.appendChild(txtLink); txtLink.click(); document.body.removeChild(txtLink); break; default: console.error('Unsupported export type:', type); break; } } function downloadPDF(htmlContent) { const element = document.createElement('div'); element.innerHTML = htmlContent; const options = { margin: 1, filename: 'download.pdf', html2canvas: { scale: 2 }, jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' } }; html2pdf() .from(element) .set(options) .save() .then(() => { document.body.removeChild(element); }) .catch(err => console.error('Error generating PDF:', err)); } function openChatWnd(wnd) { try { wnd.openChatWnd = !wnd.openChatWnd; const iframe = document.getElementById("chat-wnd-frame"); const setIframeHeight = () => { const height = window.innerHeight; iframe.style.height = (height - 50) + 'px'; }; setIframeHeight(); document.body.style.overflow = wnd.openChatWnd ? 'hidden' : ''; window.addEventListener('resize', setIframeHeight); } catch (e) { console.log(e) } }