Файловый менеджер - Редактировать - /home/gqdcvggs/ise.imators.systems/resources/views/editor.blade.php
Назад
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>IS_Engine</title> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/css2?family=Urbanist:wght@300;400;500;600;700&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.4.0/css/all.css"> <meta name="csrf-token" content="{{ csrf_token() }}"> <style> body { font-family: 'Urbanist', sans-serif; } .editor-content { min-height: 80vh; } .editor-content:empty:before { content: attr(data-placeholder); color: #9ca3af; } .toolbar { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: white; border: 1px solid #e5e7eb; border-radius: 12px; box-shadow: 0 8px 25px rgba(0,0,0,0.12); padding: 12px 20px; z-index: 50; max-width: 95vw; overflow-x: auto; } .results-bar { position: fixed; bottom: 80px; left: 50%; transform: translateX(-50%); background: url('https://ise.imators.systems/font.png'); background-size: cover; background-position: center; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 12px; box-shadow: 0 8px 25px rgba(0,0,0,0.15); padding: 12px 20px; z-index: 40; opacity: 0; visibility: hidden; transition: all 0.3s ease; display: flex; align-items: center; gap: 12px; color: white; max-width: 95vw; overflow-x: auto; } .results-bar.show { opacity: 1; visibility: visible; } .results-icon { width: 28px; height: 28px; border-radius: 50%; background: rgba(255, 255, 255, 0.2); border: 2px solid rgba(255, 255, 255, 0.3); display: flex; align-items: center; justify-content: center; color: white; font-size: 12px; flex-shrink: 0; } .btn { padding: 8px 12px; border-radius: 8px; border: 1px solid #e5e7eb; background: white; transition: all 0.2s; font-size: 14px; white-space: nowrap; cursor: pointer; } .btn:hover { background: #f3f4f6; border-color: #d1d5db; } .highlight-correct { background-color: rgba(34, 197, 94, 0.15); } .highlight-incorrect { background-color: rgba(239, 68, 68, 0.15); } .highlight-uncertain { background-color: rgba(251, 191, 36, 0.15); } .highlight-processing { background-color: rgba(59, 130, 246, 0.15); } .panel { position: fixed; background: white; border: 1px solid #e5e7eb; border-radius: 12px; box-shadow: 0 8px 25px rgba(0,0,0,0.12); padding: 20px; z-index: 45; transition: transform 0.3s ease; } .panel-save { top: 100px; right: 30px; width: 300px; transform: translateX(350px); } .panel-save.show { transform: translateX(0); } .panel-share { top: 180px; right: 30px; width: 320px; transform: translateX(370px); } .panel-share.show { transform: translateX(0); } .panel-search { top: 100px; left: 30px; width: 350px; transform: translateX(-400px); } .panel-search.show { transform: translateX(0); } .result-btn { background: rgba(255, 255, 255, 0.2); color: white; border: 1px solid rgba(255, 255, 255, 0.3); padding: 4px 8px; border-radius: 6px; font-size: 12px; cursor: pointer; transition: all 0.2s; } .result-btn:hover { background: rgba(255, 255, 255, 0.3); } </style> </head> <body class="bg-gray-50 text-black"> <header class="bg-white border-b border-gray-200 px-6 py-4 sticky top-0 z-30"> <div class="flex justify-between items-center max-w-7xl mx-auto"> <div class="flex items-center space-x-4"> <a href="/" class="text-gray-600 hover:text-black text-lg"> <i class="fas fa-arrow-left"></i> </a> <h1 class="text-xl font-medium">IS_Engine</h1> </div> <div class="flex items-center space-x-3"> <button id="save-btn" class="px-4 py-2 bg-black text-white rounded-md hover:bg-gray-800 text-sm"> Save </button> <button id="share-btn" class="px-4 py-2 border border-gray-300 rounded-md hover:bg-gray-50 text-sm"> Share </button> <span class="text-sm text-gray-600">Welcome, {{ session('username') }}</span> </div> </div> </header> <div class="max-w-4xl mx-auto px-6 py-8"> <input type="text" id="document-title-input" placeholder="Untitled Document" class="w-full text-3xl font-light border-none outline-none mb-8 placeholder-gray-400 bg-transparent"> <div id="editor" class="editor-content outline-none leading-relaxed text-gray-800 bg-white rounded-lg p-6 shadow-sm border border-gray-200" contenteditable="true" data-placeholder="Start writing..."> </div> </div> <div class="results-bar" id="results-bar"> <div class="flex-1" id="results-info"> <div class="text-sm font-medium" id="results-title">Ready</div> <div class="text-xs opacity-80" id="results-text"></div> </div> <div id="results-actions" class="flex gap-2"></div> </div> <div class="toolbar"> <div class="flex items-center space-x-2"> <button class="btn" data-action="bold"> <i class="fas fa-bold"></i> </button> <button class="btn" data-action="italic"> <i class="fas fa-italic"></i> </button> <button class="btn" data-action="underline"> <i class="fas fa-underline"></i> </button> <div class="w-px h-6 bg-gray-300 mx-2"></div> <button class="btn" data-action="h1">H1</button> <button class="btn" data-action="h2">H2</button> <button class="btn" data-action="h3">H3</button> <div class="w-px h-6 bg-gray-300 mx-2"></div> <button class="btn" data-action="bullet-list"> <i class="fas fa-list-ul"></i> </button> <button class="btn" data-action="number-list"> <i class="fas fa-list-ol"></i> </button> <div class="w-px h-6 bg-gray-300 mx-2"></div> <button class="btn" data-claude-action="grammar"> <i class="fas fa-spell-check"></i> </button> <button class="btn" data-claude-action="expand"> <i class="fas fa-expand-arrows-alt"></i> </button> <button class="btn" data-claude-action="rephrase"> <i class="fas fa-magic"></i> </button> <div class="w-px h-6 bg-gray-300 mx-2"></div> <button class="btn" id="fact-check-btn"> <i class="fas fa-search"></i> </button> <button class="btn" id="search-btn"> <i class="fas fa-globe"></i> </button> <div class="w-px h-6 bg-gray-300 mx-2"></div> <input type="text" id="quick-prompt" placeholder="Ask AI..." class="px-3 py-2 border border-gray-300 rounded text-sm" style="width: 150px;"> <button class="btn" id="send-prompt"> <i class="fas fa-paper-plane"></i> </button> </div> </div> <div class="panel panel-save" id="panel-save"> <div class="flex justify-between items-center mb-4"> <h3 class="text-lg font-medium">Save Document</h3> <button id="close-save" class="text-gray-400 hover:text-gray-600"> <i class="fas fa-times"></i> </button> </div> <input type="text" id="save-title" placeholder="Document name" class="w-full p-3 border rounded mb-4"> <div class="flex justify-end space-x-3"> <button id="cancel-save" class="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded">Cancel</button> <button id="confirm-save" class="px-4 py-2 bg-black text-white rounded hover:bg-gray-800">Save</button> </div> </div> <div class="panel panel-share" id="panel-share"> <div class="flex justify-between items-center mb-4"> <h3 class="text-lg font-medium">Share Document</h3> <button id="close-share" class="text-gray-400 hover:text-gray-600"> <i class="fas fa-times"></i> </button> </div> <div class="space-y-3 mb-4"> <label class="flex items-center p-2 border rounded cursor-pointer hover:bg-gray-50"> <input type="radio" name="share-type" value="view" class="mr-2" checked> <span class="text-sm">Read only</span> </label> <label class="flex items-center p-2 border rounded cursor-pointer hover:bg-gray-50"> <input type="radio" name="share-type" value="edit" class="mr-2"> <span class="text-sm">Allow editing</span> </label> <input type="text" id="share-link" readonly class="w-full p-3 border rounded bg-gray-50 text-sm" placeholder="Link will appear here"> </div> <div class="flex justify-end space-x-3"> <button id="cancel-share" class="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded">Cancel</button> <button id="generate-share" class="px-4 py-2 bg-black text-white rounded hover:bg-gray-800">Generate</button> <button id="copy-share" class="hidden px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600">Copy</button> </div> </div> <div class="panel panel-search" id="panel-search"> <div class="flex justify-between items-center mb-4"> <h3 class="text-lg font-medium">Search Information</h3> <button id="close-search" class="text-gray-400 hover:text-gray-600"> <i class="fas fa-times"></i> </button> </div> <input type="text" id="search-query" placeholder="What do you want to search..." class="w-full p-3 border rounded mb-4"> <div class="flex justify-end space-x-3"> <button id="cancel-search" class="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded">Cancel</button> <button id="submit-search" class="px-4 py-2 bg-black text-white rounded hover:bg-gray-800">Search</button> </div> </div> <div class="fixed inset-0 flex flex-col items-center justify-center bg-white text-center px-6 md:hidden"> <p class="text-lg text-gray-700">This site is not available on mobile. Please try again from a computer.</p> </div> <script> let currentDocument = {{ isset($document_id) ? $document_id : 'null' }}; let selectedText = ''; let selectedRange = null; let editor = document.getElementById('editor'); let autoSaveInterval; let currentSuggestion = ''; if (currentDocument) { loadDocument(currentDocument); } function showResults(title, text, actions = []) { const resultsBar = document.getElementById('results-bar'); const resultsTitle = document.getElementById('results-title'); const resultsText = document.getElementById('results-text'); const resultsActions = document.getElementById('results-actions'); resultsTitle.textContent = title; resultsText.textContent = text; resultsActions.innerHTML = ''; actions.forEach(action => { const btn = document.createElement('button'); btn.className = 'result-btn'; btn.textContent = action.text; btn.onclick = action.onclick; resultsActions.appendChild(btn); }); resultsBar.classList.add('show'); setTimeout(() => { resultsBar.classList.remove('show'); }, 8000); } async function loadDocument(id) { showResults('Loading...', 'Please wait while we load your document'); try { const response = await fetch(`/api/documents/${id}`); if (response.ok) { const document = await response.json(); document.getElementById('document-title-input').value = document.title; editor.innerHTML = document.content; showResults('Document loaded', 'Ready to edit your content'); } } catch (error) { console.error('Erreur chargement document:', error); showResults('Error', 'Could not load document'); } } function startAutoSave() { autoSaveInterval = setInterval(async () => { const title = document.getElementById('document-title-input').value; const content = editor.innerHTML; if (title.trim() !== '' || content.trim() !== '') { await saveDocument(false); } }, 30000); } async function saveDocument(showNotif = true) { const title = document.getElementById('document-title-input').value || 'Untitled Document'; const content = editor.innerHTML; if (showNotif) { showResults('Saving...', 'Saving your document'); } try { const response = await fetch('/api/documents/save', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }, body: JSON.stringify({ title: title, content: content, document_id: currentDocument }) }); const result = await response.json(); if (result.success) { currentDocument = result.document_id; if (showNotif) { showResults('Saved', 'Document saved successfully'); } } } catch (error) { console.error('Erreur sauvegarde:', error); if (showNotif) { showResults('Error', 'Could not save document'); } } } editor.addEventListener('mouseup', function() { selectedText = window.getSelection().toString().trim(); if (selectedText) { selectedRange = window.getSelection().getRangeAt(0).cloneRange(); } }); document.querySelectorAll('[data-action]').forEach(button => { button.addEventListener('click', function() { const action = this.dataset.action; executeCommand(action); }); }); function executeCommand(action) { switch(action) { case 'bold': document.execCommand('bold'); break; case 'italic': document.execCommand('italic'); break; case 'underline': document.execCommand('underline'); break; case 'h1': document.execCommand('formatBlock', false, 'h1'); break; case 'h2': document.execCommand('formatBlock', false, 'h2'); break; case 'h3': document.execCommand('formatBlock', false, 'h3'); break; case 'bullet-list': document.execCommand('insertUnorderedList'); break; case 'number-list': document.execCommand('insertOrderedList'); break; } editor.focus(); } document.querySelectorAll('[data-claude-action]').forEach(button => { button.addEventListener('click', function() { const action = this.dataset.claudeAction; if (selectedText) { highlightSelectedText('processing'); showResults('Processing...', `AI is working on ${action}`, []); callClaudeAPI('', action); } else { showResults('No selection', 'Please select text first'); } }); }); document.getElementById('send-prompt').addEventListener('click', () => { const prompt = document.getElementById('quick-prompt').value; if (prompt.trim()) { if (selectedText) { highlightSelectedText('processing'); } showResults('Processing...', 'AI is thinking about your request'); callClaudeAPI(prompt, 'custom'); document.getElementById('quick-prompt').value = ''; } }); document.getElementById('quick-prompt').addEventListener('keypress', (e) => { if (e.key === 'Enter') { document.getElementById('send-prompt').click(); } }); async function callClaudeAPI(prompt, action) { try { const response = await fetch('/api/claude', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }, body: JSON.stringify({ prompt: prompt, selected_text: selectedText, action: action }) }); const result = await response.json(); if (result.success) { let cleanContent = result.content; const introPatterns = [ /^Voici le texte corrigé :\s*/i, /^Texte corrigé :\s*/i, /^Version développée :\s*/i, /^Résumé :\s*/i, /^Reformulation :\s*/i, /^Voici une reformulation :\s*/i, /^Voici un résumé :\s*/i, /^Voici le texte développé :\s*/i ]; introPatterns.forEach(pattern => { cleanContent = cleanContent.replace(pattern, ''); }); const endPatterns = [ /\.\s*Il n'y a aucune erreur.*$/i, /\.\s*Ce texte ne contient.*$/i, /\.\s*La phrase est déjà.*$/i ]; endPatterns.forEach(pattern => { cleanContent = cleanContent.replace(pattern, '.'); }); cleanContent = cleanContent.trim(); currentSuggestion = cleanContent; if (selectedText && selectedRange) { highlightSelectedText('correct'); showResults(`${action} suggestion`, cleanContent.substring(0, 100) + '...', [ { text: 'Apply', onclick: () => applySuggestion() }, { text: 'Dismiss', onclick: () => clearHighlights() } ]); } else { showResults('AI Response', cleanContent.substring(0, 100) + '...', [ { text: 'Insert', onclick: () => insertAtCursor(cleanContent) } ]); } } else { if (selectedText) { clearHighlights(); } showResults('AI Error', 'Request failed, please try again'); } } catch (error) { if (selectedText) { clearHighlights(); } console.error('Erreur Claude API:', error); showResults('Connection Error', 'Check your internet connection'); } } function applySuggestion() { if (selectedRange && currentSuggestion) { const selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(selectedRange); if (selection.rangeCount > 0) { const range = selection.getRangeAt(0); range.deleteContents(); range.insertNode(document.createTextNode(currentSuggestion)); } clearHighlights(); selectedText = ''; selectedRange = null; currentSuggestion = ''; showResults('Applied', 'Changes applied successfully'); } } function insertAtCursor(text) { const selection = window.getSelection(); if (selection.rangeCount > 0) { const range = selection.getRangeAt(0); range.insertNode(document.createTextNode(text + ' ')); } else { editor.appendChild(document.createTextNode(text + ' ')); } editor.focus(); showResults('Inserted', 'Content added to document'); } document.getElementById('fact-check-btn').addEventListener('click', () => { const documentText = editor.textContent.trim(); if (documentText) { showResults('Fact-checking...', 'Analyzing your content for accuracy'); analyzeDocument(documentText); } else { showResults('Empty document', 'Write something first to fact-check'); } }); async function analyzeDocument(text) { try { const response = await fetch('/api/fact-check', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }, body: JSON.stringify({ text: text }) }); const result = await response.json(); if (result.success) { highlightFactCheckResults(result.analysis); const correctCount = result.analysis.filter(item => item.status === 'correct').length; const totalCount = result.analysis.length; showResults('Fact-check complete', `${correctCount}/${totalCount} statements verified`); } else { showResults('Fact-check failed', 'Could not analyze content'); } } catch (error) { console.error('Erreur fact check:', error); showResults('Connection Error', 'Check your internet connection'); } } document.getElementById('search-btn').addEventListener('click', () => { document.getElementById('panel-search').classList.add('show'); }); document.getElementById('submit-search').addEventListener('click', () => { const query = document.getElementById('search-query').value; if (query.trim()) { showResults('Searching...', 'Looking up information on the web'); callPerplexityAPI(query); document.getElementById('panel-search').classList.remove('show'); } }); document.getElementById('cancel-search').addEventListener('click', () => { document.getElementById('panel-search').classList.remove('show'); }); document.getElementById('close-search').addEventListener('click', () => { document.getElementById('panel-search').classList.remove('show'); }); async function callPerplexityAPI(query) { try { const response = await fetch('/api/search', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }, body: JSON.stringify({ query: query }) }); const result = await response.json(); if (result.success) { showResults('Search Results', result.summary.substring(0, 100) + '...', [ { text: 'Insert', onclick: () => insertAtCursor(result.summary) } ]); } else { showResults('Search failed', 'Could not find information'); } } catch (error) { console.error('Erreur recherche:', error); showResults('Connection Error', 'Check your internet connection'); } } function highlightSelectedText(type) { if (selectedRange) { const span = document.createElement('span'); span.className = `highlight-${type}`; try { selectedRange.surroundContents(span); } catch (e) { console.log('Cannot highlight complex selection'); } } } function highlightFactCheckResults(analysis) { clearHighlights(); const editorText = editor.textContent; analysis.forEach(item => { if (item.statement) { const regex = new RegExp(item.statement.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi'); editor.innerHTML = editor.innerHTML.replace(regex, `<span class="highlight-${item.status}">${item.statement}</span>`); } }); } function clearHighlights() { const highlights = editor.querySelectorAll('[class*="highlight-"]'); highlights.forEach(highlight => { const parent = highlight.parentNode; parent.replaceChild(document.createTextNode(highlight.textContent), highlight); parent.normalize(); }); } document.getElementById('save-btn').addEventListener('click', () => { document.getElementById('save-title').value = document.getElementById('document-title-input').value; document.getElementById('panel-save').classList.add('show'); }); document.getElementById('confirm-save').addEventListener('click', async () => { const title = document.getElementById('save-title').value; document.getElementById('document-title-input').value = title; document.getElementById('panel-save').classList.remove('show'); await saveDocument(true); }); document.getElementById('cancel-save').addEventListener('click', () => { document.getElementById('panel-save').classList.remove('show'); }); document.getElementById('close-save').addEventListener('click', () => { document.getElementById('panel-save').classList.remove('show'); }); document.getElementById('share-btn').addEventListener('click', () => { if (!currentDocument) { showResults('Document not saved', 'Save your document first'); return; } document.getElementById('panel-share').classList.add('show'); }); document.getElementById('generate-share').addEventListener('click', async () => { const permission = document.querySelector('input[name="share-type"]:checked').value; showResults('Generating...', 'Creating share link'); try { const response = await fetch(`/api/documents/${currentDocument}/share`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }, body: JSON.stringify({ permission: permission }) }); const result = await response.json(); if (result.success) { document.getElementById('share-link').value = result.share_url; document.getElementById('copy-share').classList.remove('hidden'); showResults('Link generated', 'Share link is ready to copy'); } else { showResults('Generation failed', 'Could not create share link'); } } catch (error) { console.error('Erreur partage:', error); showResults('Connection Error', 'Check your internet connection'); } }); document.getElementById('copy-share').addEventListener('click', () => { const shareLink = document.getElementById('share-link'); shareLink.select(); document.execCommand('copy'); showResults('Link copied', 'Share link copied to clipboard'); }); document.getElementById('cancel-share').addEventListener('click', () => { document.getElementById('panel-share').classList.remove('show'); document.getElementById('share-link').value = ''; document.getElementById('copy-share').classList.add('hidden'); }); document.getElementById('close-share').addEventListener('click', () => { document.getElementById('panel-share').classList.remove('show'); document.getElementById('share-link').value = ''; document.getElementById('copy-share').classList.add('hidden'); }); document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { document.getElementById('panel-save').classList.remove('show'); document.getElementById('panel-share').classList.remove('show'); document.getElementById('panel-search').classList.remove('show'); document.getElementById('results-bar').classList.remove('show'); clearHighlights(); } }); startAutoSave(); window.addEventListener('beforeunload', () => { if (autoSaveInterval) { clearInterval(autoSaveInterval); } }); showResults('Operational', 'Start writing your document'); </script> </body> </html>
| ver. 1.6 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка