// Generate Google Apps Script function generateScript(columns) { return ` function doGet(e) { try { const action = e.parameter.action; const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); switch (action) { case 'search': return handleSearchGet(sheet, e.parameter.q); case 'fetch': const startRow = e.parameter.startRow ? parseInt(e.parameter.startRow) : null; const endRow = e.parameter.endRow ? parseInt(e.parameter.endRow) : null; return handleFetchGet(sheet, startRow, endRow); default: return ContentService.createTextOutput(JSON.stringify({ error: 'Invalid action.' })).setMimeType(ContentService.MimeType.JSON); } } catch (error) { Logger.log(error); return ContentService.createTextOutput(JSON.stringify({ error: error.message })).setMimeType(ContentService.MimeType.JSON); } } function doPost(e) { try { if (e.postData.type !== 'application/json') { return ContentService.createTextOutput(JSON.stringify({ error: 'Invalid content type. Only JSON is accepted.' })).setMimeType(ContentService.MimeType.JSON); } const data = JSON.parse(e.postData.contents); const action = data.action; const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); switch (action) { case 'append': return handleAppend(sheet, data.rows); case 'search': return handleSearch(sheet, data.q); case 'update': return handleUpdate(sheet, data.row, ${columns.map(col => `data.${col}`).join(', ')}); case 'delete': return handleDelete(sheet, data.row); case 'fetch': return handleFetch(sheet, data.row, data.endRow); default: return ContentService.createTextOutput(JSON.stringify({ error: 'Invalid action.' })).setMimeType(ContentService.MimeType.JSON); } } catch (error) { Logger.log(error); return ContentService.createTextOutput(JSON.stringify({ error: error.message })).setMimeType(ContentService.MimeType.JSON); } } function handleAppend(sheet, rows) { if (!Array.isArray(rows) || rows.length === 0) { return ContentService.createTextOutput(JSON.stringify({ error: 'Invalid rows data.' })).setMimeType(ContentService.MimeType.JSON); } const values = rows.map(row => [${columns.map(col => `row.${col}`).join(', ')}]); sheet.getRange(sheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values); return ContentService.createTextOutput(JSON.stringify({ success: true, rowsAdded: rows.length })).setMimeType(ContentService.MimeType.JSON); } function handleSearch(sheet, query) { if (!query) { return ContentService.createTextOutput(JSON.stringify({ error: 'Search query is required.' })).setMimeType(ContentService.MimeType.JSON); } const data = sheet.getDataRange().getValues(); const results = data.filter(row => ${columns.map((col, i) => `row[${i}].toLowerCase().includes(query.toLowerCase())`).join(' || ')}); return ContentService.createTextOutput(JSON.stringify(results)).setMimeType(ContentService.MimeType.JSON); } function handleSearchGet(sheet, query) { if (!query) { return ContentService.createTextOutput(JSON.stringify({ error: 'Search query is required.' })).setMimeType(ContentService.MimeType.JSON); } const data = sheet.getDataRange().getValues(); const results = data.filter(row => ${columns.map((col, i) => `row[${i}].toLowerCase().includes(query.toLowerCase())`).join(' || ')}); return ContentService.createTextOutput(JSON.stringify(results)).setMimeType(ContentService.MimeType.JSON); } function handleUpdate(sheet, rowIndex, ${columns.join(', ')}) { if (!rowIndex || ${columns.map(col => `!${col}`).join(' || ')}) { return ContentService.createTextOutput(JSON.stringify({ error: 'Invalid update data.' })).setMimeType(ContentService.MimeType.JSON); } const row = rowIndex + 1; if (row > sheet.getLastRow()) { return ContentService.createTextOutput(JSON.stringify({ error: 'Row index out of range.' })).setMimeType(ContentService.MimeType.JSON); } ${columns.map((col, i) => ` sheet.getRange(row, ${i + 1}).setValue(${col});`).join('\n')} return ContentService.createTextOutput(JSON.stringify({ success: true })).setMimeType(ContentService.MimeType.JSON); } function handleDelete(sheet, rowIndex) { if (!rowIndex) { return ContentService.createTextOutput(JSON.stringify({ error: 'Row index is required.' })).setMimeType(ContentService.MimeType.JSON); } const row = rowIndex + 1; if (row > sheet.getLastRow()) { return ContentService.createTextOutput(JSON.stringify({ error: 'Row index out of range.' })).setMimeType(ContentService.MimeType.JSON); } sheet.deleteRow(row); return ContentService.createTextOutput(JSON.stringify({ success: true })).setMimeType(ContentService.MimeType.JSON); } function handleFetch(sheet, startRow, endRow) { const lastRow = sheet.getLastRow(); startRow = startRow ? startRow + 1 : 1; endRow = endRow ? endRow + 1 : lastRow; if (startRow > lastRow || endRow > lastRow || startRow > endRow) { return ContentService.createTextOutput(JSON.stringify({ error: 'Invalid row range.' })).setMimeType(ContentService.MimeType.JSON); } const data = sheet.getRange(startRow, 1, endRow - startRow + 1, ${columns.length}).getValues(); return ContentService.createTextOutput(JSON.stringify(data)).setMimeType(ContentService.MimeType.JSON); } function handleFetchGet(sheet, startRow, endRow) { const lastRow = sheet.getLastRow(); startRow = startRow ? startRow + 1 : 1; endRow = endRow ? endRow + 1 : lastRow; if (startRow > lastRow || endRow > lastRow || startRow > endRow) { return ContentService.createTextOutput(JSON.stringify({ error: 'Invalid row range.' })).setMimeType(ContentService.MimeType.JSON); } const data = sheet.getRange(startRow, 1, endRow - startRow + 1, ${columns.length}).getValues(); return ContentService.createTextOutput(JSON.stringify(data)).setMimeType(ContentService.MimeType.JSON); }`.trim(); } // Generate cURL examples as an object function generateCurlExamples(columns) { const sampleValues = columns.map((col, i) => [col, `Sample ${col} ${i + 1}`]); return { appendSingle: ` curl -X POST "https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec" \\ -H "Content-Type: application/json" \\ -d '{ "action": "append", "rows": [{ ${sampleValues.map(([col, val]) => `"${col}": "${val}"`).join(',\n ')} }] }'`.trim(), appendMultiple: ` curl -X POST "https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec" \\ -H "Content-Type: application/json" \\ -d '{ "action": "append", "rows": [ { ${sampleValues.map(([col, val]) => `"${col}": "${val}"`).join(', ')} }, { ${sampleValues.map(([col, val]) => `"${col}": "Another ${val}"`).join(', ')} } ] }'`.trim(), fetchAll: ` curl "https://script.google.com/macros/s/YOUR_WEB_APP_ID/exec?action=fetch"`.trim(), fetchRange: ` curl "https://script.google.com/macros/s/YOUR_WEB_APP_ID/exec?action=fetch&startRow=50&endRow=100"`.trim(), search: ` curl "https://script.google.com/macros/s/YOUR_WEB_APP_ID/exec?action=search&q=sample"`.trim(), update: ` curl -X POST "https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec" \\ -H "Content-Type: application/json" \\ -d '{ "action": "update", "row": 50, ${sampleValues.map(([col, val]) => `"${col}": "Updated ${val}"`).join(',\n ')} }'`.trim(), delete: ` curl -X POST "https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec" \\ -H "Content-Type: application/json" \\ -d '{ "action": "delete", "row": 100 }'`.trim() }; } // Update previews function updatePreviews() { const columns = Array.from(document.querySelectorAll('.column-input')) .map(input => input.value.trim()) .filter(value => value !== ''); document.getElementById('codePreview').textContent = generateScript(columns); const curlExamples = generateCurlExamples(columns); const activeButton = document.querySelector('.curl-button.active'); const exampleKey = activeButton ? activeButton.getAttribute('onclick').match(/'([^']+)'/)[1] : 'appendSingle'; document.getElementById('curlExamples').textContent = curlExamples[exampleKey]; } // Add new column function addColumn() { const container = document.getElementById('columnInputs'); const div = document.createElement('div'); div.innerHTML = `
`; container.appendChild(div); updatePreviews(); } // Remove column function removeColumn(button) { button.parentElement.parentElement.remove(); updatePreviews(); } // Tab switching function showTab(tabId) { document.querySelectorAll('.tab-content').forEach(tab => tab.classList.remove('active')); document.getElementById(tabId).classList.add('active'); document.querySelectorAll('.tab-button').forEach(btn => btn.classList.remove('border-blue-500')); event.target.classList.add('border-blue-500'); } // Show specific cURL example function showCurlExample(exampleKey) { const columns = Array.from(document.querySelectorAll('.column-input')) .map(input => input.value.trim()) .filter(value => value !== ''); const curlExamples = generateCurlExamples(columns); document.getElementById('curlExamples').textContent = curlExamples[exampleKey]; document.querySelectorAll('.curl-button').forEach(btn => btn.classList.remove('active')); event.target.classList.add('active'); } // Copy code to clipboard function copyCode() { const code = document.getElementById('codePreview').textContent; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(code).then(() => { alert('Code copied to clipboard!'); }).catch(err => { console.error('Failed to copy: ', err); fallbackCopy(code); }); } else { fallbackCopy(code); } } // Fallback for older browsers or restricted environments function fallbackCopy(text) { const textArea = document.createElement('textarea'); textArea.value = text; document.body.appendChild(textArea); textArea.select(); try { document.execCommand('copy'); alert('Code copied to clipboard!'); } catch (err) { alert('Failed to copy code. Please copy it manually.'); } document.body.removeChild(textArea); } // Initialize document.addEventListener('DOMContentLoaded', () => { updatePreviews(); document.getElementById('columnInputs').addEventListener('input', updatePreviews); // Set default active cURL button const firstCurlButton = document.querySelector('.curl-button'); if (firstCurlButton) { firstCurlButton.classList.add('active'); } });