Spaces:
Running
Running
| // Add this new function | |
| function toggleSidebar() { | |
| const sidebar = document.getElementById('sidebar'); | |
| sidebar.classList.toggle('open'); | |
| } | |
| // Update the DOMContentLoaded event listener | |
| document.addEventListener('DOMContentLoaded', () => { | |
| updatePreviews(); | |
| document.getElementById('columnInputs').addEventListener('input', updatePreviews); | |
| const firstCurlButton = document.querySelector('.curl-button'); | |
| if (firstCurlButton) { | |
| firstCurlButton.classList.add('active'); | |
| } | |
| // Ensure sidebar is closed on mobile by default | |
| if (window.innerWidth < 768) { | |
| document.getElementById('sidebar').classList.remove('open'); | |
| } | |
| }); | |
| // 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 = ` | |
| <div class="flex space-x-2"> | |
| <input type="text" class="column-input flex-1 px-3 py-2 border rounded-md" placeholder="Column name"> | |
| <button onclick="removeColumn(this)" class="bg-red-500 text-white px-2 py-1 rounded hover:bg-red-600">X</button> | |
| </div> | |
| `; | |
| 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'); | |
| } | |
| }); |