CoolFace
Apppublic

Alph4Centauri/email-summerization-ui

sourceHugging Faceapache-2.0updated 1y agoView on Hugging Face
0likes
taskpane.js404 linesDownload Raw Back to root
1const BACKEND_URL = 'https://Alph4Centauri-email-summarization-api.hf.space';2 3Office.onReady((info) => {4    if (info.host === Office.HostType.Outlook) {5        if (document.readyState === 'loading') {6            document.addEventListener('DOMContentLoaded', init);7        } else {8            init();9        }10    }11});12 13function init() {14    const summarizeBtn = document.getElementById('summarize-btn');15    const copyBtn = document.getElementById('copy-btn');16    17    if (summarizeBtn) summarizeBtn.onclick = generateSummary;18    if (copyBtn) copyBtn.onclick = copySummary;19    20    initParsingOptions();21}22 23function initParsingOptions() {24    const includeAttachments = document.getElementById('include-attachments');25    const includeEmail = document.getElementById('include-email');26    const attachmentOptions = document.getElementById('attachment-options');27    const sectionOptions = document.getElementById('section-options');28    29    if (includeAttachments && attachmentOptions) {30        includeAttachments.addEventListener('change', function() {31            attachmentOptions.classList.toggle('disabled', !this.checked);32        });33    }34    35    if (includeEmail && includeAttachments && sectionOptions) {36        function updateSectionOptions() {37            const bothSelected = includeEmail.checked && includeAttachments.checked;38            sectionOptions.classList.toggle('disabled', !bothSelected);39            40            if (!bothSelected) {41                document.querySelector('input[name="output-mode"][value="combined"]').checked = true;42            }43        }44        45        includeEmail.addEventListener('change', updateSectionOptions);46        includeAttachments.addEventListener('change', updateSectionOptions);47        updateSectionOptions();48    }49}50 51function showElement(id) {52    document.getElementById(id).style.display = 'block';53}54 55function hideElement(id) {56    document.getElementById(id).style.display = 'none';57}58 59function showMessage(type, message) {60    ['info-bar', 'error-message', 'success-message'].forEach(hideElement);61    62    const elementId = type === 'info' ? 'info-bar' : type + '-message';63    const element = document.getElementById(elementId);64    65    if (element) {66        element.textContent = message;67        showElement(elementId);68        69        if (type === 'success') {70            setTimeout(() => hideElement(elementId), 3000);71        }72    }73}74 75function getEmailContent() {76    return new Promise((resolve, reject) => {77        Office.context.mailbox.item.body.getAsync(Office.CoercionType.Text, (result) => {78            if (result.status === Office.AsyncResultStatus.Succeeded) {79                getAttachments()80                    .then(attachments => resolve({ emailBody: result.value, attachments }))81                    .catch(reject);82            } else {83                reject(new Error('Failed to get email body: ' + result.error.message));84            }85        });86    });87}88 89function getAttachments() {90    return new Promise((resolve) => {91        const attachments = Office.context.mailbox.item.attachments;92        93        if (!attachments || attachments.length === 0) {94            resolve([]);95            return;96        }97        98        const promises = attachments.map(attachment => {99            return new Promise((resolveAtt) => {100                if (attachment.attachmentType === Office.MailboxEnums.AttachmentType.File) {101                    Office.context.mailbox.item.getAttachmentContentAsync(attachment.id, (result) => {102                        if (result.status === Office.AsyncResultStatus.Succeeded) {103                            resolveAtt({104                                name: attachment.name,105                                content: result.value.content,106                                contentType: result.value.format107                            });108                        } else {109                            resolveAtt({110                                name: attachment.name,111                                content: null,112                                error: result.error.message113                            });114                        }115                    });116                } else {117                    resolveAtt({118                        name: attachment.name,119                        content: null,120                        type: 'item'121                    });122                }123            });124        });125        126        Promise.all(promises).then(resolve);127    });128}129 130async function sendToBackend(emailData) {131    const summaryType = document.getElementById('summary-type').value;132    const includeEmail = document.getElementById('include-email').checked;133    const includeAttachments = document.getElementById('include-attachments').checked;134    const attachmentMode = document.querySelector('input[name="attachment-mode"]:checked')?.value || 'combined';135    const outputMode = document.querySelector('input[name="output-mode"]:checked')?.value || 'combined';136    137    const requestData = {138        ...emailData,139        summaryType,140        parsingOptions: { includeEmail, includeAttachments, attachmentMode, outputMode }141    };142    143    const response = await fetch(`${BACKEND_URL}/summarize`, {144        method: 'POST',145        headers: { 'Content-Type': 'application/json' },146        body: JSON.stringify(requestData)147    });148 149    const result = await response.json();150 151    if (!response.ok) {152        throw new Error(result.error);153    }154 155    if (!result.success) {156        throw new Error(result.error || 'Unknown error occurred');157    }158    159    return result;160}161 162async function generateSummary() {163    const summarizeBtn = document.getElementById('summarize-btn');164    const summaryContainer = document.getElementById('summary-container');165    const summaryContent = document.getElementById('summary-content');166    const summaryTypeDropdown = document.getElementById('summary-type');167    168    if (!summarizeBtn || !summaryContent || !summaryTypeDropdown) {169        showMessage('error', 'UI elements not found. Please refresh the add-in.');170        return;171    }172    173    const includeEmail = document.getElementById('include-email')?.checked || false;174    const includeAttachments = document.getElementById('include-attachments')?.checked || false;175    176    if (!includeEmail && !includeAttachments) {177        showMessage('error', 'Please select at least one content type to summarize.');178        return;179    }180    181    try {182        const selectedOption = summaryTypeDropdown.options[summaryTypeDropdown.selectedIndex];183        const summaryTypeName = selectedOption.text;184        const outputMode = document.querySelector('input[name="output-mode"]:checked')?.value || 'combined';185        const attachmentMode = document.querySelector('input[name="attachment-mode"]:checked')?.value || 'combined';186        187        summarizeBtn.disabled = true;188        summarizeBtn.textContent = 'Processing...';189        summaryTypeDropdown.disabled = true;190        toggleParsingControls(true);191        192        showElement('loading');193        ['summary-container', 'info-bar', 'error-message', 'success-message'].forEach(hideElement);194        195        showMessage('info', 'Extracting content...');196        const emailData = await getEmailContent();197        198        const contentDesc = [];199        if (includeEmail) contentDesc.push('email body');200        if (includeAttachments) {201            const attachCount = emailData.attachments.length;202            if (attachCount > 0) {203                const mode = attachmentMode === 'separate' ? 'individually' : 'combined';204                contentDesc.push(`${attachCount} attachments (${mode})`);205            } else {206                contentDesc.push('attachments (none found)');207            }208        }209        210        const processingMsg = `Generating ${summaryTypeName} for: ${contentDesc.join(' + ')}${outputMode === 'sections' ? ' (separate sections)' : ''}...`;211        showMessage('info', processingMsg);212        213        const result = await sendToBackend(emailData);214        215        if (result.summaryData?.sections) {216            displaySections(result.summaryData.sections);217        } else {218            summaryContent.textContent = result.summary || 'No summary generated.';219        }220        221        if (summaryContainer) showElement('summary-container');222        223        let successMsg = `${summaryTypeName} generated successfully`;224        if (result.attachmentsProcessed > 0) {225            successMsg += ` (${result.attachmentsProcessed} attachments processed)`;226        }227        showMessage('success', successMsg);228        229    } catch (error) {230        showMessage('error', error.message);231    } finally {232        summarizeBtn.disabled = false;233        summarizeBtn.textContent = 'Generate Summary';234        summaryTypeDropdown.disabled = false;235        toggleParsingControls(false);236        hideElement('loading');237    }238}239 240function toggleParsingControls(disabled) {241    const controls = [242        'include-email',243        'include-attachments',244        ...document.querySelectorAll('input[name="attachment-mode"]'),245        ...document.querySelectorAll('input[name="output-mode"]')246    ];247    248    controls.forEach(ctrl => {249        const element = typeof ctrl === 'string' ? document.getElementById(ctrl) : ctrl;250        if (element) element.disabled = disabled;251    });252}253 254function displaySections(sections) {255    const summaryContent = document.getElementById('summary-content');256    if (!summaryContent) return;257    258    const output = sections.map((section, index) => {259        let text = '';260        if (section.title) {261            text += `\n${'='.repeat(50)}\n${section.title.toUpperCase()}\n${'='.repeat(50)}\n\n`;262        }263        text += section.content;264        return text;265    }).join('\n\n');266    267    summaryContent.textContent = output.trim();268}269 270async function copySummary() {271    const summaryContent = document.getElementById('summary-content');272    const copyBtn = document.getElementById('copy-btn');273    274    if (!summaryContent || !copyBtn) {275        showMessage('error', 'Copy elements not found');276        return;277    }278    279    const text = summaryContent.textContent;280    if (!text?.trim()) {281        showMessage('error', 'No summary content to copy');282        return;283    }284    285    try {286        if (navigator.clipboard?.writeText) {287            await navigator.clipboard.writeText(text);288            showCopySuccess(copyBtn);289            return;290        }291        292        const textarea = document.createElement('textarea');293        Object.assign(textarea.style, {294            position: 'fixed',295            left: '-9999px',296            opacity: '0'297        });298        textarea.value = text;299        300        document.body.appendChild(textarea);301        textarea.select();302        303        const success = document.execCommand('copy');304        document.body.removeChild(textarea);305        306        if (success) {307            showCopySuccess(copyBtn);308        } else {309            selectTextForManualCopy(summaryContent, copyBtn);310        }311        312    } catch (error) {313        showCopyModal(text);314    }315}316 317function showCopySuccess(btn) {318    const originalText = btn.textContent;319    const originalColor = btn.style.backgroundColor;320    321    btn.textContent = 'Copied!';322    btn.style.backgroundColor = '#28a745';323    324    setTimeout(() => {325        btn.textContent = originalText;326        btn.style.backgroundColor = originalColor || '#28a745';327    }, 2000);328    329    showMessage('success', 'Summary copied to clipboard!');330}331 332function selectTextForManualCopy(content, btn) {333    const range = document.createRange();334    range.selectNodeContents(content);335    const selection = window.getSelection();336    selection.removeAllRanges();337    selection.addRange(range);338    339    const originalText = btn.textContent;340    btn.textContent = 'Selected!';341    btn.style.backgroundColor = '#17a2b8';342    343    setTimeout(() => {344        btn.textContent = originalText;345        btn.style.backgroundColor = '#28a745';346        if (window.getSelection) window.getSelection().removeAllRanges();347    }, 3000);348    349    showMessage('success', 'Text selected! Press Ctrl+C to copy.');350}351 352function showCopyModal(text) {353    const existingModal = document.getElementById('copy-modal');354    if (existingModal) existingModal.remove();355    356    const modal = document.createElement('div');357    modal.id = 'copy-modal';358    modal.style.cssText = `359        position: fixed; top: 0; left: 0; right: 0; bottom: 0;360        background: rgba(0,0,0,0.7); display: flex; align-items: center;361        justify-content: center; z-index: 10000; padding: 20px;362    `;363    364    modal.innerHTML = `365        <div style="background: white; border-radius: 8px; padding: 20px; max-width: 90%; max-height: 80%; overflow: auto; box-shadow: 0 4px 20px rgba(0,0,0,0.3);">366            <h3 style="margin-top: 0; color: #2c3e50;">Copy Summary</h3>367            <p style="color: #666; margin-bottom: 15px;">Select all text below and copy manually:</p>368            <textarea readonly style="width: 100%; height: 200px; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-family: inherit; resize: vertical; box-sizing: border-box;">${text}</textarea>369            <div style="text-align: right; margin-top: 15px;">370                <button onclick="this.closest('#copy-modal').remove()" style="background: #0078d4; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer;">Close</button>371            </div>372        </div>373    `;374    375    document.body.appendChild(modal);376    377    setTimeout(() => {378        const textarea = modal.querySelector('textarea');379        if (textarea) {380            textarea.select();381            textarea.focus();382        }383    }, 100);384    385    modal.addEventListener('click', (e) => {386        if (e.target === modal) modal.remove();387    });388}389 390function displaySections(sections) {391    const summaryContent = document.getElementById('summary-content');392    if (!summaryContent) return;393    394    const output = sections.map(section => {395        let text = '';396        if (section.title) {397            text += `\n${'='.repeat(50)}\n${section.title.toUpperCase()}\n${'='.repeat(50)}\n\n`;398        }399        text += section.content;400        return text;401    }).join('\n\n');402    403    summaryContent.textContent = output.trim();404}