Creating a script to add a record to Airtable

I think you’ve got a number of control flow issues with your script. The actual interaction with Airtable does not use the app, it communicates directly with the Airtable API. If you are wanting Airtable to open when the script is done, you can do that - but do NOT use a CallbackURL object - which is intended for triggering actions in other apps with will return results back to Drafts. Using CallbackURL makes Drafts wait for a response from AirTable - which is never going to get - which hangs the action framework waiting.

Instead just use app.openURL("Airtable://") at the end of the script - or include a “Open URL” action step after the script in the action.

This is not tested, as I don’t have your DBs, but I did a quick pass simplifying your flow and removing the CallbackURL usage. Try this:

let basename = "";
let airtableURL = "airtable://";

(() => {
	let p = Prompt.create();
	p.addButton("Add to existing record");
	p.addButton("Create a new record");

	if (!p.show()) {
		context.cancel();
		return;
	}
	switch (p.buttonPressed) {
		case "Add to existing record":
			// put draft in clipboard and optn Airtable app
			app.setClipboard(draft.content);
			app.openURL(airtableURL);
			break;
		case "Create a new record":
			chooseBase();
			break;
	}
})()

function chooseBase() {
	let p = Prompt.create();
	p.addButton("Add to Equipment");
	p.addButton("Add to Inventory");

	if (!p.show()) {
		context.cancel();
		return;
	}
	switch (p.buttonPressed) {
		case "Add to Equipment":
			basename = "Equipment";
			addRecord();
			break;
		case "Add to Inventory":
			basename = "Inventory";
			addRecord();
			break;
	}
}

function addRecord() {
	var options = ["accessories", "apple", "bagsandcontainers", "cables", "chargers", "children", "clothes", "healthandhygiene", "luxury", "photography", "stationery", "tech", "tools"];
	var selectedOptions = [];
	var base = ATBase.create(basename);
	var main = ATTable.create("Main", base);
	var newRecord = ATRecord.create();

	if (basename == "Equipment") {
		let p1 = Prompt.create();
		p1.addTextField("name", "Name:", "");
		p1.addTextField("attachments", "Attachments:", "");
		p1.addSelect("tags", "Tags:", options, selectedOptions, true);
		p1.addSwitch("edc", "EDC:", false);
		p1.addSwitch("purchased", "Purchased:", false);
		p1.addTextField("notes", "Notes:", "");

		p1.addButton("OK");
		if (!p1.show()) {
			context.cancel();
			return;
		}

		newRecord.setFieldValue("Name", p1.fieldValues['name']);
		newRecord.setFieldValue("Attachments", p1.fieldValues['attachments']);
		newRecord.setFieldValue("Tags", p1.fieldValues['tags']);
		newRecord.setFieldValue("EDC", p1.fieldValues['edc']);
		newRecord.setFieldValue("Purchased", p1.fieldValues['purchased']);
		newRecord.setFieldValue("Notes", p1.fieldValues['notes']);
	} else if (basename == "Inventory") {
		let p2 = Prompt.create();
		p2.addTextField("name", "Name:", "");
		p2.addTextField("model", "Model:", "");
		p2.addTextField("purchasedate", "Purchase Date:", "DD/MM/YYYY");
		p2.addTextField("purchaselocation", "Purchase Location:", "");
		p2.addTextField("warranty", "Warranty:", "");
		p2.addTextField("serialnumbers", "Serial Number(s):", "");
		p2.addTextField("notes", "Notes:", "");
		p2.addTextField("manuals", "Manual(s):", "");

		p2.addButton("OK");
		if (!p2.show()) {
			context.cancel();
			return;
		}

		newRecord.setFieldValue("Name", p2.fieldValues['name']);
		newRecord.setFieldValue("Model", p2.fieldValues['model']);
		newRecord.setFieldValue("Purchase Date", p2.fieldValues['purchasedate']);
		newRecord.setFieldValue("Purchase Location", p2.fieldValues['purchaselocation']);
		newRecord.setFieldValue("Warranty", p2.fieldValues['warranty']);
		newRecord.setFieldValue("Serial Number(s)", p2.fieldValues['serialnumbers']);
		newRecord.setFieldValue("Notes", p2.fieldValues['notes']);
		newRecord.setFieldValue("Manual(s)", p2.fieldValues['manuals']);
	}

	main.addRecord(newRecord);
	if (main.update()) {
		// created record successfully
		console.log("Item added to Airtable");
		app.openURL(airtableURL);
	} else {
		console.log("Airtable API call failed");
		context.fail();
	}
}
1 Like

@agiletortoise Thanks for your help - that works!

I’ve run in to a problem with my script.

The Attachments field for the Equipment base and the Manual(s) field for the Inventory base are both text fields populated by a string generated via user input; however, the Airtable API expects an ‘array of attachment objects’ (URLs to files, images, etc.)

Is there a way of either (a) converting the string to an array acceptable by the API, or (b) entering the user input directly as an array?

Thanks in advance,

Martin

Try putting square brackets around the string.

Eg. ["foo"]

@sylumer Which statement needs the brackets?

For example, with the Equipment base, the ‘addTextField’ method is expecting string parameters, so changing

p1.addTextField("attachments", "Attachments:", "");

to

p1.addTextField("attachments", "Attachments:", [""]);

still results in the following error from the Airtable API script:

Script Error: TypeError: undefined is not an object (evaluating ‘httpRequest.responseData.id’).

If the brackets are to go in the following statement, then I’m unsure where to put them, as wrapping either of the strings in brackets also results in the same error.

newRecord.setFieldValue("Attachments", p1.fieldValues['attachments']);

What am I missing?

Thanks!

In your examples above it looks like you are putting arrays into string parameters. You don’t want to be changing the input parameters of your prompt. Otherwise it simply will break something else in your script. Think about getting the data from your prompt, and putting that into one or more arrays as per your use for AirTable.

Have you studied arrays in programming before, and specifically in JavaScript? If not, maybe try a quick primer like this:

https://www.w3schools.com/js/js_arrays.asp

After that, try the following little array-based script giving a few examples of adding strings to an array. You can run this in a Drafts script action step, and you’ll see it coming up with undefined (on purpose) in several places. Hopefully, it’ll help make sense of what’s probably going on, and you should make sure you understand what has happened at each stage. It’ll help you debug your data and structures for arrays in the furture is not now.

let strFoo = "foo";
let strQuz = "quz";
let astrArray = [strFoo, "bar"];
alert("First array element is - " + astrArray[0]);
alert("Second array element is - " + astrArray[1]);
alert("Third array element is - " + astrArray[2]);
astrArray.push(strQuz);
alert("Third array element is now - " + astrArray[2]);
alert("Fourth array element is - " + astrArray[3]);
astrArray.push("qux");
alert("Fourth array element is now - " + astrArray[3]);
astrArray.push("");
alert("Fifth array element is now - " + astrArray[5]);
astrArray.push();
alert("Sixth array element is now - " + astrArray[6]);
astrArray.push(undefined);
alert("Sixth array element is now - " + astrArray[6]);
astrArray.push("I am the seventh element");
alert("'" + astrArray.join("' '") + "'");

Hope that helps.