### Install Dependencies with Bun
Source: https://github.com/indexsupply/shovel/blob/main/shovel-config-ts/build-instructions.txt
Use this command to install project dependencies using the Bun package manager.
```bash
bun install
```
--------------------------------
### Download and Install Latest Shovel from Main
Source: https://github.com/indexsupply/shovel/blob/main/readme.md
Use these commands to download the latest Shovel version from the main branch for macOS ARM64 and make it executable.
```bash
curl -LO https://indexsupply.net/bin/main/darwin/arm64/shovel --silent
chmod +x shovel
```
--------------------------------
### Download and Install Shovel v1.6
Source: https://github.com/indexsupply/shovel/blob/main/readme.md
Use these commands to download Shovel version 1.6 for macOS ARM64, make it executable, and verify the installation.
```bash
curl -LO https://indexsupply.net/bin/1.6/darwin/arm64/shovel --silent
chmod +x shovel
./shovel -version
```
```text
v1.6 582d
```
--------------------------------
### Display Generated Password
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/login.html
This example shows the format of a randomly generated temporary password found in the logs. It is used when authentication is enabled but no password has been explicitly set.
```log
password=171658e9feca092b msg=random-temp-password
```
--------------------------------
### Get Chain Configuration for Integration
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Extracts configuration for 'chain' type integrations. It collects names and optional start values for checked chain rows, used for defining data processing chains.
```javascript
function getChains(eventDiv) {
let res = []
eventDiv.querySelectorAll("tr.chain").forEach(row => {
let cb = row.querySelector(`input[type="checkbox"]`);
if (!cb || !cb.checked) {
return;
}
let src = {};
src.name = row.querySelector("td.name").textContent.trim();
const s = row.querySelector(`input[type="number"]`).valueAsNumber;
if (s > 0) {
src.start = s;
}
res.push(src);
});
return res;
}
```
--------------------------------
### HTML Table Row for Source Chain Information
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Generates an HTML table row to display information about a source chain, including its name, chain ID, and a field for backfill start.
```javascript
function srcRow(src) { return
`
${src.name}
${src.chain_id}
`; }
```
--------------------------------
### JavaScript Progress Calculation
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/index.html
Calculates the progress percentage based on start and stop values. Returns '100%' if the stop value is 0 or if the calculated progress reaches 100%.
```javascript
function progress(start, stop) { if (stop == 0) { return "100%"; } const p = (start / stop) * 100; if (p == 100) { return "100%"; } else { return `${p.toFixed(2)}%`; } };
```
--------------------------------
### Get Block Metadata for Integration
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Extracts metadata for 'block' type integrations from the UI. It iterates through rows marked as metadata, collecting names and database column mappings for checked items.
```javascript
function getBlock(eventDiv) {
let res = []
eventDiv.querySelectorAll("tr.metadata").forEach(row => {
let cb = row.querySelector(`input[type="checkbox"]`);
if (!cb || !cb.checked) {
return;
}
let n = row.querySelector("td.name").textContent.trim()
let c = row.querySelector("td.dbName span").textContent.trim();
res.push({name: n, column: c});
});
return res;
}
```
--------------------------------
### Get Event Data for Integration
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Retrieves the event data, including selected fields and their mapped database columns, from the UI. It updates the event schema based on user selections and returns the modified event document.
```javascript
function getEvent(eventDiv, doc) {
let name = eventName(eventDiv);
let eventDoc = doc.find(e => {
return e.type == 'event' && e.name == name;
});
if (!event) {
return {};
}
eventDiv.querySelectorAll("tr.field:not(.metadata)").forEach(row => {
let cb = row.querySelector(`input[type="checkbox"]`);
if (!cb) {
return;
}
if (cb.checked) {
let dbColumn = row.querySelector("td.dbName span").textContent.trim();
setColumn(eventDoc, getPath(eventDiv, row), dbColumn);
} else {
setColumn(eventDoc, getPath(eventDiv, row), "");
}
});
return eventDoc;
}
```
--------------------------------
### Get Table Selection
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Retrieves the currently selected table from the event's table selection dropdown. This is used to determine which table the event data should be associated with.
```javascript
function getTable(eventDiv) {
let tableSelect = eventDiv.querySelector(".eventTable select");
return tableSelect.options[tableSelect.selectedIndex].text;
}
```
--------------------------------
### Get Event Field Path
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Constructs the hierarchical path for a given event field row within its event div. It traverses up the parent elements using 'data-parent' attributes to build the path.
```javascript
function getPath(eventDiv, row) {
let path = []
for (;;) {
path.push(row.dataset.field)
row = eventDiv.querySelector(`[data-field="${row.dataset.parent}"]`);
if (!row) {
break;
}
}
return path.reverse();
}
```
--------------------------------
### Build Project with Bun
Source: https://github.com/indexsupply/shovel/blob/main/shovel-config-ts/build-instructions.txt
Execute this command to build the project using Bun. This typically compiles source code and prepares assets.
```bash
bun run build
```
--------------------------------
### Publish to npm Registry
Source: https://github.com/indexsupply/shovel/blob/main/shovel-config-ts/build-instructions.txt
Use this command to publish the project to the npm registry. Ensure you are logged in and have the correct version set.
```bash
npm publish
```
--------------------------------
### Publish to JSR Registry with Bunx
Source: https://github.com/indexsupply/shovel/blob/main/shovel-config-ts/build-instructions.txt
This command publishes the project to the JSR registry using Bunx. This is an alternative to npm publishing.
```bash
bunx jsr publish
```
--------------------------------
### Build Shovel Docker Image
Source: https://github.com/indexsupply/shovel/blob/main/cmd/shovel/readme.txt
Build the Shovel Docker image using the provided Dockerfile. This command should be run from the root directory of the project.
```bash
docker build -t shovel:latest -f ./cmd/shovel/Dockerfile .
```
--------------------------------
### Populate Network Details on Chain ID Input
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-source.html
This script populates the network name and ETH URL when a Chain ID is entered. It uses a map to find the corresponding details and a debounced timer to avoid excessive lookups.
```javascript
let nameMap = { 1: {name: "Mainnet", url: "https://1.rlps.indexsupply.net"}, 5: {name: "Goerli", url: "https://5.rlps.indexsupply.net"}, 10: {name: "Optimism", url: "https://10.rlps.indexsupply.net"}, 420: {name: "Optimism Goerli", url: "https://420.rlps.indexsupply.net"}, 8453: {name: "Base", url: "https://8453.rlps.indexsupply.net"}, 84531: {name: "Base Goerli", url: "https://84531.rlps.indexsupply.net"} }
document.addEventListener("DOMContentLoaded", function() { let done = function(v) { let config = nameMap[v]; let name = ""; let url = ""; if (config) { name = config.name; url = config.url; } document.querySelector("#name").value = name; document.querySelector("#ethURL").value = url; } const waitTime = 200; let timer; let chainID = document.querySelector("#chainID"); chainID.addEventListener("keyup", e => { clearTimeout(timer); timer = setTimeout(function() { done(e.target.value); }, waitTime); }); });
```
--------------------------------
### Suggest Table Name from Event
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Placeholder function for suggesting a database table name based on an event object.
```javascript
function suggestTableName(event)
```
--------------------------------
### Link Shovel Config Locally with Bun
Source: https://github.com/indexsupply/shovel/blob/main/shovel-config-ts/build-instructions.txt
This command links the local Shovel configuration package for development purposes, allowing you to test changes without publishing.
```bash
bun link @indexsupply/shovel-config
```
--------------------------------
### Generate Shovel Configuration with TypeScript
Source: https://github.com/indexsupply/shovel/blob/main/shovel-config-ts/readme.md
Defines a data source, a table schema, and an integration rule to capture Ethereum transfer events. Use this to script complex Shovel configurations programmatically.
```typescript
import { makeConfig, toJSON } from "@indexsupply/shovel-config";
import type { Source, Table, Integration } from "@indexsupply/shovel-config";
const table: Table = {
name: "transfers",
columns: [
{ name: "log_addr", type: "bytea" },
{ name: "from", type: "bytea" },
{ name: "to", type: "bytea" },
{ name: "amount", type: "numeric" },
],
};
const mainnet: Source = {
name: "mainnet",
chain_id: 1,
url: "https://ethereum.publicnode.com",
};
let integrations: Integration[] = [
{
enabled: true,
name: "transfers",
sources: [{ name: mainnet.name, start: 0n }],
table: table,
block: [
{
name: "log_addr",
column: "log_addr",
filter_op: "contains",
filter_arg: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"],
},
],
event: {
type: "event",
name: "Transfer",
inputs: [
{ indexed: true, name: "from", type: "address", column: "from" },
{ indexed: true, name: "to", type: "address", column: "to" },
{ indexed: false, name: "amount", type: "uint256", column: "amount" },
],
},
},
];
const config = makeConfig({
pg_url: "postgres:///shovel",
sources: [mainnet],
integrations: integrations,
});
console.log(toJSON(config));
```
--------------------------------
### ABI Document Test Data
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Provides a sample ABI (Application Binary Interface) document structure used for testing purposes. This data represents event inputs and outputs, including complex types like tuples and arrays.
```json
const abiDocTest = [
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes32",
"name": "orderHash",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "offerer",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "zone",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"components": [
{
"internalType": "enum ItemType",
"name": "itemType",
"type": "uint8"
},
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "identifier",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"indexed": false,
"internalType": "struct SpentItem[]",
"name": "offer",
"type": "tuple[]"
},
{
"components": [
{
"internalType": "enum ItemType",
"name": "itemType",
"type": "uint8"
},
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "identifier",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"internalType": "address payable",
"name": "recipient",
"type": "address"
}
],
"indexed": false,
"internalType": "struct ReceivedItem[]",
"name": "consideration",
"type": "tuple[]"
}
],
"name": "OrderFulfilled",
"type": "event"
}
];
```
--------------------------------
### Drag and Drop ABI Document Loading
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Handles loading an ABI document via drag and drop. Parses the dropped file as JSON and updates the `abiDoc` variable.
```javascript
var abiDoc = null; document.addEventListener("DOMContentLoaded", function() { let dropArea = document.querySelector('#abiDocDrop'); dropArea.addEventListener('dragover', (event) => { event.stopPropagation(); event.preventDefault(); event.dataTransfer.dropEffect = 'copy'; }); dropArea.addEventListener('drop', (event) => { event.stopPropagation(); event.preventDefault(); dropArea.style.display = 'none'; const reader = new FileReader(); reader.addEventListener('load', (event) => { abiDoc = JSON.parse(event.target.result); processEvents(abiDoc); }); reader.readAsText(event.dataTransfer.files[0]); }); });
```
--------------------------------
### Enable Debug Mode with Keyboard Shortcut
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Toggles debug mode on/off when the '/' key is pressed. In debug mode, outlines are added to all elements, and the ABI document display is altered.
```javascript
document.addEventListener("DOMContentLoaded", function() { var debug = false; document.addEventListener('keydown', function(e) { if (e.keyCode != 191) { return; } debug = !debug; if (debug) { document.querySelectorAll('*').forEach(el => { el.style.setProperty('outline', '1px dotted red'); }); abiDoc = abiDocTest; document.querySelector('#abiDocDrop').style.display = 'none'; processEvents(abiDocTest); } else { document.querySelectorAll('*').forEach(el => { el.style.removeProperty('outline'); }); } }); });
```
--------------------------------
### Generate Event Mapping HTML
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Constructs the complete HTML structure for an event mapping, including chain sources, event data fields, and block metadata. Assumes `ethSources` is globally available.
```javascript
function eventMapping(event) { let rows = []; rows.push(seperator("Chains")); ethSources.forEach(c => { rows.push(srcRow(c)) }); rows.push(seperator("Event Data")); event.inputs.forEach(field => { row(0, event, event, field).forEach(r => { rows.push(r); }); }); rows.push(seperator("Block Data")); metadata.forEach(field => { rows.push(metadataRow(0, event, event, field)); }); return
`
${rows.join("\n")}
`; }
```
--------------------------------
### Determine Database Type from ABI Type
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Maps an ABI type string to a database type. Currently, 'uint' types map to 'numeric', and others map to 'bytea'.
```javascript
function dbType(abiType) { switch (true) { case abiType.trim().startsWith("uint"): return "numeric"; default: return "bytea"; } }
```
--------------------------------
### Save Integration Data
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Handles the submission of integration configuration. It gathers data from the UI and sends it to the server via a POST request. Upon successful save, it redirects the user to the integration's detail page.
```javascript
function eventName(eventDiv) { return eventDiv.querySelector(".eventMapping table").dataset.field; }
document.querySelectorAll(\`.eventMapping input[type="submit"]").forEach(input => {
input.addEventListener("click", e => {
let eventDiv = input.closest('.event');
let integration = {};
integration["name"] = eventName(eventDiv);
integration["enabled"] = true;
integration["sources"] = getChains(eventDiv);
integration["table"] = getTable(eventDiv);
integration["block"] = getBlock(eventDiv);
integration["event"] = getEvent(eventDiv, abiDoc);
console.log(integration);
post("/save-integration", integration).then(d => {
location.href = `/integration/${integration.name}`;
}).catch(e => {
console.log(e);
});
});
});
async function post(url, data) {
const resp = await fetch(url, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(data)
});
return resp.json();
}
```
--------------------------------
### Update Login Configuration
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/login.html
This snippet demonstrates how to update the Shovel configuration file to manage authentication. You can either disable authentication by setting `disable_authn` to `true` or update the password by changing `root_password`.
```json
"dashboard": {
"disable_authn": false,
"root_password": "XXX",
}
```
--------------------------------
### Expand/Collapse Event Details
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Toggles the visibility of event details, including tables and mapping configurations, when an event name is clicked. This provides a way to show or hide detailed information for each event.
```javascript
document.querySelectorAll('.eventName').forEach( e => {
e.addEventListener('click', c => {
e.classList.toggle("expand");
let eventDiv = e.closest('.event');
eventDiv.querySelectorAll('.eventTable').forEach(t => {
if (t.style.display == 'flex') {
t.style.display = 'none';
} else {
t.style.display = 'flex';
}
});
eventDiv.querySelectorAll('.eventMapping').forEach(t => {
if (t.style.display == 'flex') {
t.style.display = 'none';
} else {
t.style.display = 'flex';
}
});
});
});
```
--------------------------------
### JavaScript DOMContentLoaded and Event Listeners
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/index.html
Initializes event listeners when the DOM is fully loaded. Includes a keydown listener for toggling display of '.destinations' elements and a listener for 'task-updates' Server-Sent Events to update task information in real-time.
```javascript
document.addEventListener("DOMContentLoaded", function() { document.addEventListener('keydown', function(e) { if (e.keyCode == 73) { document.querySelectorAll('.destinations').forEach(el => { const d = el.style.display; el.style.display = (d == 'none' ? '' : 'none'); }); } }); document.querySelectorAll(".addComma").forEach(e => { e.innerText = comma(e.innerText); }); let updates = new EventSource("/task-updates"); updates.onmessage = function(event) { const tu = JSON.parse(event.data); if (tu.Hash) { update(tu.DOMID, "Num", comma(tu.Num)); update(tu.DOMID, "Hash", tu.Hash); update(tu.DOMID, "Latency", tu.Latency); update(tu.DOMID, "NRows", tu.NRows); } else { update(tu.DOMID, "Latency", tu.Latency); update(tu.DOMID, "NRows", tu.NRows); } }; });
```
--------------------------------
### HTML Table Row for Metadata Fields
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Generates an HTML table row for metadata fields associated with an event. Displays name, type, database name, and database type.
```javascript
function metadataRow(depth, parent, event, field) { return
`
${field.name}
${field.type}
→
${dbName(parent, field)}
${dbType(field.type)}
`; }
```
--------------------------------
### Generate Database Field Name
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Generates a database-friendly name for a field based on its name and parent context. Special cases 'from' and 'to' fields.
```javascript
function dbName(parent, field) { if (field.name == "from") { return "f" } if (field.name == "to") { return "t" } if (!parent.components) { return snake(field.name); } return
`${parent.name[0]}
_
${snake(field.name)}
` }
```
--------------------------------
### HTML Rendering Helper
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
A utility function to render HTML content into a target DOM element. It creates a temporary div, sets its innerHTML, and appends the first child element to the target.
```javascript
function render(target, html) {
const tmp = document.createElement("div");
tmp.innerHTML = html;
target.appendChild(tmp.firstElementChild);
}
```
--------------------------------
### Snake Case Conversion Utility
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Converts a string to snake_case. Handles underscores and capital letters to create the snake_case format.
```javascript
function snake(s) { let res = ''; for (let i = 0; i < s.length; i++) { if (s[i] === "_") { res += s[i].toLowerCase(); } else if (i > 0 && s[i] === s[i].toUpperCase()) { res += '_' + s[i].toLowerCase(); } else { res += s[i].toLowerCase(); } } return res; }
```
--------------------------------
### Process and Render Events
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Processes an array of events, rendering each event's HTML structure into the main content area of the page. It also ensures that event listeners are added after rendering.
```javascript
function processEvents(events) {
let main = document.querySelector("main");
events.forEach(e => {
if (e.type == 'event') {
let node = render(main, eventDiv(e));
}
});
addListeners();
}
```
--------------------------------
### HTML Table Row for Event Fields
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Generates an HTML table row for a regular event field. Includes name, type, database name, database type, and a checkbox.
```javascript
function fieldRow(depth, parent, event, field) { return
`
${field.name}
${field.type}
→
${dbName(parent, field)}
${dbType(field.type)}
`; }
```
--------------------------------
### Render Event HTML
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Renders an event's header, including its name and table selection, along with its mapping details. This function is used to construct the HTML for displaying individual events on the web page.
```javascript
function eventHeader(event) { return
`
`;
}
```
--------------------------------
### JavaScript Number Formatting
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/index.html
Formats a number by adding locale-specific comma separators. Converts the input string to a Number before formatting.
```javascript
function comma(s) { return Number(s).toLocaleString(); };
```
--------------------------------
### HTML Table Row for Tuple Fields
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Generates an HTML table row for a tuple field within an event mapping. Includes name, type, and checkbox for selection.
```javascript
function tupleRow(depth, parent, field) { return `
${field.name}
${field.type}
`; };
```
--------------------------------
### Metadata Fields Definition
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Defines a list of metadata fields with their names and types, used for event mapping.
```javascript
const metadata = [{"name": "chain_id", "type": "uint16"}, {"name": "block_hash", "type": "bytes32"}, {"name": "block_num", "type": "uint256"}, {"name": "tx_hash", "type": "bytes32"}, {"name": "tx_idx", "type": "uint16"}, {"name": "tx_signer", "type": "address"}, {"name": "tx_to", "type": "address"}, {"name": "tx_value", "type": "uint256"}, {"name": "log_idx", "type": "uint16"}, {"name": "log_addr", "type": "address"} ];
```
--------------------------------
### HTML Table Row for Separators
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Generates an HTML table row to act as a visual separator with a given text label.
```javascript
function seperator(text) { return `
${text}
`; }
```
--------------------------------
### Handle Field Selection Changes
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Listens for changes on field checkboxes within the event mapping table. It updates the state of parent tuples and headers accordingly to maintain data integrity and UI consistency.
```javascript
// fieldRow
document.querySelectorAll('.eventMapping table tr.field input[type="checkbox"]').forEach(cb => {
cb.addEventListener('change', c => {
let row = cb.closest('tr');
let eventDiv = cb.closest('.event');
let parentKey = row.dataset.parent;
let parentRow = eventDiv.querySelector(`[data-tuple="${parentKey}"]`);
if (!parentRow) {
checkHeader(eventDiv);
return
}
checkTuple(parentRow);
checkHeader(eventDiv);
});
});
```
--------------------------------
### Drag and Drop Row Swapping
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Enables drag-and-drop functionality for table rows, allowing users to reorder fields within the event mapping. It captures the dragged row and swaps its position with the target row upon dropping.
```javascript
var draggedRow = null;
document.querySelectorAll('tr[draggable="true"]').forEach(d => {
d.addEventListener('dragstart', function(e) {
draggedRow = e.target.closest('tr');
});
d.addEventListener('dragover', function(e) {
e.preventDefault();
});
d.addEventListener('drop', function(e) {
swapRows(draggedRow, e.target.parentElement)
});
});
```
--------------------------------
### Recursive Row Generation for Event Fields
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Recursively generates HTML table rows for event fields, handling nested components (tuples) by increasing the depth.
```javascript
function row(depth, parent, event, field) { let res = []; if (!('components' in field)) { res.push(fieldRow(depth, parent, event, field)); return res; } res.push(tupleRow(depth, parent, field)); field.components.forEach(function(comp, i, arr) { row(depth+1, field, event, comp).forEach(r => { res.push(r); }); }); return res; }
```
--------------------------------
### Toggle All Event Fields
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Allows users to select or deselect all field checkboxes within an event mapping by toggling a single checkbox in the event header. This simplifies bulk selection.
```javascript
document.querySelectorAll('.eventHeader input[type="checkbox"]').forEach(cb => {
cb.addEventListener('change', c => {
cb.closest('.event').querySelectorAll('.eventMapping table input[type="checkbox"]').forEach(fcb => {
fcb.checked = cb.checked;
})
});
});
```
--------------------------------
### Update Event Header Checkbox
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Updates the state of the main event header checkbox based on whether any checkboxes within the event's mapping table are checked. This provides a summary status for the entire event.
```javascript
// Update the event's header checkbox if any of the event's checkboxes // are checked.
function checkHeader(eventDiv) {
var numChecked = 0;
eventDiv.querySelectorAll('.eventMapping table input[type="checkbox"]:checked').forEach(cb => {
numChecked++;
});
eventDiv.querySelector('.eventHeader input[type="checkbox"]').checked = numChecked > 0;
}
```
--------------------------------
### Add Event Listeners
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Attaches event listeners to various elements within the event display, including table cells for toggling checkboxes and checkboxes themselves for handling changes. This function enables user interaction with the event data.
```javascript
function addListeners() {
document.querySelectorAll('.eventMapping table td:not(.nocheck)').forEach(r => {
r.addEventListener('click', c => {
let row = r.closest('tr');
let cb = row.querySelector('input[type="checkbox"]');
cb.checked ^= 1;
cb.dispatchEvent(new Event("change"));
});
});
document.querySelectorAll('.eventMapping table tr.tuple input[type="checkbox"]').forEach(cb => {
cb.addEventListener('change', c => {
let eventDiv = cb.closest('.event');
let row = cb.closest('tr');
let tupleKey = row.dataset.tuple;
if (tupleKey == "") {
return;
}
// update all immediate children
eventDiv.querySelectorAll(`[data-parent="${tupleKey}"] input[type="checkbox"]`).forEach(ccb => {
ccb.checked = cb.checked;
});
// recursively call this function
// on all child tuple checkboxes.
eventDiv.querySelectorAll(`[data-tuple][data-parent="${tupleKey}"] input[type="checkbox"]`).forEach(ccb => {
ccb.dispatchEvent(new Event("change"));
});
let parentKey = cb.closest('tr').dataset.parent;
if (parentKey == "") {
checkHeader(eventDiv);
return
}
checkTuple(eventDiv.querySelector(`[data-tuple="${parentKey}"]`));
checkHeader(eventDiv);
});
});
}
```
--------------------------------
### Swap Table Row Content
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Swaps the text content of cells between two table rows. This is useful for reordering or rearranging data within a table structure.
```javascript
function swapRows(x, y) {
for (var i = 0; i < x.cells.length; i++) {
var tmp = x.cells\[i\]\.textContent;
x.cells\[i\]\.textContent = y.cells\[i\]\.textContent;
y.cells\[i\]\.textContent = tmp;
}
}
```
--------------------------------
### JavaScript DOM Update Function
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/index.html
Updates the text content of a specific field within a task's DOM element. It finds the task element by its ID and then the specific field element by its class name.
```javascript
function update(id, field, val) { const taskDiv = document.getElementById(id); const fieldDiv = taskDiv.querySelector(`.${field}`); fieldDiv.innerText = val; };
```
--------------------------------
### Set Column in Event Schema
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Updates the 'column' property for a specific field within an event's schema definition. It traverses the schema path to find the correct input component and assigns the provided database column value.
```javascript
// abidata
function setColumn(doc, path, value) {
path.shift(); //ignore event name
let input = null;
let inputs = doc.inputs;
path.forEach(pathName => {
input = inputs.find(inp => inp.name == pathName);
if (!input) {
return undefined;
}
inputs = input.components;
});
input["column"] = value
}
```
--------------------------------
### Check Tuple Checkbox State
Source: https://github.com/indexsupply/shovel/blob/main/shovel/web/add-integration.html
Updates the state of a parent checkbox based on the checked status of its child checkboxes within a tuple. It recursively checks parent tuples up the hierarchy.
```javascript
function checkTuple(row) {
let eventDiv = row.closest('.event');
let checkBox = row.querySelector(`input[type="checkbox"]`);
let tupleKey = row.dataset.tuple;
if (tupleKey == "") {
return;
}
var numChecked = 0;
eventDiv.querySelectorAll(`[data-parent="${tupleKey}"] input[type="checkbox"]`).forEach(childCheckbox => {
if (childCheckbox.checked) {
numChecked++;
}
});
checkBox.checked = numChecked > 0;
let parentKey = row.dataset.parent;
if (parentKey == "") {
return;
}
eventDiv.querySelectorAll(`[data-tuple="${parentKey}"]`).forEach(prow => {
checkTuple(prow);
});
}
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.