Spaces:
Running
Running
// 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'); | |
} | |
}); |