Instantly share code, notes, and snippets.
Created
July 9, 2021 21:45
-
Save kuovonne/d39fb93e630ca70883e7c2e0b97c6783 to your computer and use it in GitHub Desktop.
Airtable Script - Same Table Back Links
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************************************************************************************************** | |
Name: Same Table Back Links | |
Date: July 9, 2021 | |
Author: Kuovonne Vorderbruggen | |
Website: https://atmosphere.kuovonne.com | |
## Description | |
Create backlinks for a table with same-table linked records | |
## Usage | |
1. Copy and paste this script into Scripting App. | |
2. Click the "settings gear" for Scripting app and set the table and fields. No code changes necessary. | |
3. Click the "run" button for the script. | |
## license | |
This script is provided "as is", without warranty of any kind. Liability of the | |
author will be limited to a maximum of the original purchase price of the script. | |
The author will not be liable for any general, special, incidental, or consequential | |
damages. | |
***************************************************************************************************** | |
*/ | |
/******************************************************************************* | |
Script Configuration Settings | |
******************************************************************************* | |
*/ | |
const inputConfig = input.config({ | |
title: 'Create back links for same-table links', | |
items: [ | |
input.config.table('table', { | |
label: 'Table with same-table links', | |
}), | |
input.config.field('fldLinkAuthority', { | |
label: 'Original Link', | |
description: 'This linked record field is the "source of truth" for links. Its values will not be changed.', | |
parentTable: 'table', | |
}), | |
input.config.field('fldBackLink', { | |
label: 'Back Link field', | |
description: 'This linked record field will be updated to match information in the original link field.', | |
parentTable: 'table', | |
}), | |
] | |
}); | |
/******************************************************************************* | |
Main function for the script | |
******************************************************************************* | |
*/ | |
await main() | |
output.markdown("## Done") | |
/*******************************************************************************/ | |
async function main() { | |
if (!checkSettings()) { return } | |
const userContinue = await input.buttonsAsync(`Update backlinks in ${inputConfig.table.name}?`, ["Continue", "Cancel"]) | |
if (userContinue == "Cancel") { | |
return | |
} | |
const queryResult = await inputConfig.table.selectRecordsAsync({fields: [ | |
inputConfig.fldLinkAuthority, | |
inputConfig.fldBackLink, | |
]}) | |
output.markdown(`Records to examine: ${queryResult.records.length}`) | |
// setup map of backlinks by recordId | |
let linkMap = {} | |
for (const record of queryResult.records) { | |
const currentBacklinks = record.getCellValue(inputConfig.fldBackLink) | |
linkMap[record.id] = { | |
currentBacklinkIds: (currentBacklinks ? currentBacklinks.map(obj => obj.id) : []), | |
newBacklinkIds: [], // to be filled in later in script | |
} | |
} | |
// fill in newBacklinkIds | |
for (const record of queryResult.records) { | |
const linkedValue = record.getCellValue(inputConfig.fldLinkAuthority) | |
if (!linkedValue) {continue} | |
for (const obj of linkedValue) { | |
linkMap[obj.id].newBacklinkIds.push(record.id) | |
} | |
} | |
// figure out which records need updating | |
let recordsToUpdate = [] | |
for (const recordId of Object.keys(linkMap)) { | |
const currentBacklinkIds = linkMap[recordId].currentBacklinkIds | |
const newBacklinkIds = linkMap[recordId].newBacklinkIds | |
if ( (currentBacklinkIds.length == newBacklinkIds.length) && currentBacklinkIds.every(value => newBacklinkIds.includes(value))) { | |
continue // this recordId doesn't need updating | |
} | |
recordsToUpdate.push({ | |
id: recordId, | |
fields: { | |
[inputConfig.fldBackLink.name]: newBacklinkIds.map(id => ({id: id})) | |
} | |
}) | |
} | |
output.markdown(`Records to update: ${recordsToUpdate.length}`) | |
while (recordsToUpdate.length > 0) { | |
await inputConfig.table.updateRecordsAsync(recordsToUpdate.slice(0, 50)); | |
recordsToUpdate = recordsToUpdate.slice(50); | |
} | |
} | |
/*******************************************************************************/ | |
function checkSettings() { | |
if ( | |
(inputConfig.fldLinkAuthority.type != "multipleRecordLinks") | |
|| (inputConfig.fldBackLink.type != "multipleRecordLinks") | |
|| (inputConfig.fldLinkAuthority.options.linkedTableId != inputConfig.table.id) | |
|| (inputConfig.fldBackLink.options.linkedTableId != inputConfig.table.id) | |
|| (inputConfig.fldBackLink.id == inputConfig.fldLinkAuthority.id) | |
) { | |
output.markdown("Check fields in settings.") | |
return false | |
} | |
return true | |
} | |
/******************************************************************************* | |
END OF SCRIPT | |
******************************************************************************* | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment