-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
33 changed files
with
10,486 additions
and
795 deletions.
There are no files selected for viewing
Binary file not shown.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Create a prefilled form | ||
As part of an airtable URL we are able to use *query parameters* to prefill certain values. | ||
|
||
## How this works | ||
We take our form url and provide a series of additional query parameters following the `?`. | ||
|
||
Here for example if we wanted to fill the `Name` field, we might add: | ||
``` | ||
prefill_Name=Bob | ||
``` | ||
|
||
|
||
## Script | ||
```python | ||
''' | ||
Author and Maintainer contact | ||
daniel.ellis (at) ext.esa.int | ||
''' | ||
|
||
def generate_airtable_form_url(base_id, table_name, fields): | ||
""" | ||
Generates a pre-filled Airtable form URL with the given base ID, table name, and pre-fill fields. | ||
Args: | ||
base_id (str): The unique identifier of the Airtable base. | ||
table_name (str): The name of the Airtable table. | ||
fields (dict): A dictionary containing pre-fill field names as keys and corresponding values. | ||
Returns: | ||
str: The pre-filled Airtable form URL. | ||
Example: | ||
>>> base_id = 'xxxxxxxxxxx' | ||
>>> table_name = 'yyyyyyyyyy' | ||
>>> fields = { | ||
... 'Name': 'York', | ||
... 'ROR': 'https://ror.org/04m01e293', | ||
... 'Assignee': 'Dan' | ||
... } | ||
>>> generate_airtable_form_url(base_id, table_name, fields) | ||
'https://airtable.com/appaZflpqbFjA6pwV/shrNALXGlKZAk76iD?prefill_Name=York&prefill_ROR=https://ror.org/04m01e293&prefill_Assignee=dan' | ||
""" | ||
base_url = f'https://airtable.com/{base_id}/{table_name}' | ||
# Construct the URL parameters for pre-filling the form fields | ||
params = "&".join([f'prefill_{key}={value}' for key, value in fields.items()]) | ||
airtable_form_url = f'{base_url}?{params}' | ||
return airtable_form_url | ||
|
||
# Example usage | ||
if __name__ == "__main__": | ||
# Replace the following values with your actual base ID, table name, and pre-fill fields | ||
|
||
# table / form information | ||
base_id = 'xxxxxxxxxxx' | ||
table_name = 'yyyyyyyyyy' | ||
|
||
# A dictionary containing the field name -> value of those which we want to prefill. | ||
# an example is given below | ||
fields = { | ||
'Name': 'York', | ||
'ROR': 'https://ror.org/04m01e293', | ||
'Assignee': 'Dan' | ||
} | ||
|
||
# Generate the pre-filled Airtable form URL | ||
|
||
airtable_form_url = generate_airtable_form_url(base_id, table_name, fields) | ||
|
||
print(f'Pre-filled Airtable form URL: {airtable_form_url}') | ||
``` |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
# Using the fetchAPI (currency converter) | ||
Airtable is able to run scripts periodically or on a variety of triggers. In this case we write a script that checks the conversion rate between two currencies and updates a column of our table. | ||
|
||
! tip Note | ||
Due to limitations in the Airtable API we have to process and update our records in batches. In this example we use groupings of 50. | ||
|
||
## Script | ||
|
||
```js | ||
console.log(`Hello, ${base.name}!`); | ||
|
||
/* | ||
Airtable template made for the CMIP-IPO | ||
All queries: contact the IPO Technical Officer: | ||
Daniel Ellis | ||
daniel.ellis -@- ext.esa.int | ||
Before usage the | ||
- tablename, | ||
- currency, | ||
- amount, | ||
- output field | ||
- and last_updated | ||
columns need to be present, and correctly referenced within this script | ||
Usage and ammendments to this script are permitted, but correct reference of the origin (this) and any changes are required. | ||
*/ | ||
|
||
|
||
//////////////////////////////////////////////////// | ||
// Configuration options to change! | ||
//////////////////////////////////////////////////// | ||
const tablename = 'Per Diem'; | ||
const output_currency = 'EUR' | ||
// fileds | ||
const currency = 'Currency'; | ||
const amount = 'Per Diem amount'; | ||
const output_field = 'Per Diem in Euros'; | ||
const last_updated = 'Last updated'; | ||
//////////////////////////////////////////////////// | ||
const apiKey = '<need to enter key here>' | ||
|
||
let table = base.getTable(tablename); | ||
let conversions = {}; | ||
|
||
async function get_rate(currency){ | ||
/* A function to get the latest conversion rate */ | ||
|
||
const url = `https://api.apilayer.com/exchangerates_data/latest?base=${currency}`; | ||
|
||
|
||
if (conversions.hasOwnProperty(currency)){ | ||
return conversions[currency] | ||
}else{ | ||
|
||
// Fetch conversion rate from API - you could change this to any API you want | ||
let apiResponse = await fetch(url,{ | ||
method: 'GET', | ||
headers: { | ||
'apikey': apiKey, | ||
}}); | ||
let data = await apiResponse.json(); | ||
console.log(data) | ||
|
||
|
||
console.log(data) | ||
let conversionRate = data.rates[output_currency]; | ||
|
||
conversions[currency] = conversionRate || -1 | ||
|
||
return conversions[currency] | ||
} | ||
|
||
} | ||
|
||
// retrieve the table | ||
let result = await table.selectRecordsAsync({fields: [currency,amount]}); | ||
|
||
let inputConfig = input.config(); | ||
console.log(inputConfig); | ||
|
||
const now = new Date().toISOString().split('T')[0]; | ||
|
||
|
||
|
||
// Create an array to hold update operations | ||
let updateOperations = []; | ||
|
||
// Prepare updates for each record | ||
for (let record of result.records) { | ||
let currency_value = record.getCellValue(currency); | ||
let amount_value = record.getCellValue(amount); | ||
|
||
let conversion_value = await get_rate(currency_value); | ||
|
||
|
||
let updates = { | ||
id: record.id, | ||
fields: { | ||
[output_field]: amount_value * conversion_value, | ||
[last_updated]: `Conversion (${currency_value}): ${conversion_value} @ ${now}` | ||
} | ||
}; | ||
|
||
updateOperations.push(updates); | ||
} | ||
|
||
// Update records in batches | ||
const batchSize = 50; // Set the batch size according to your needs | ||
for (let i = 0; i < updateOperations.length; i += batchSize) { | ||
let batch = updateOperations.slice(i, i + batchSize); | ||
await table.updateRecordsAsync(batch); | ||
} | ||
|
||
``` |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
# Creating a GitHub Issue | ||
In relation to a form submit or new value entry, we might want to perfrom an error check to ensure that our date is conformant, or accurate. | ||
|
||
Although it is possible to set up an automation to email, we may want a more visible solution - especially when we are working with an open source community - where the issue relates not to one individual or group. | ||
|
||
One way to do this it to create a github issue. | ||
The following script take form input and compiles it into a template, which can then be discussed, or ingested by a GitHub action. | ||
|
||
## Script | ||
```js | ||
/* | ||
Airtable template made for the CMIP-IPO | ||
All queries: contact the IPO Technical Officer: | ||
Daniel Ellis | ||
daniel.ellis -@- ext.esa.int | ||
Make sure that each label is '- ' delimited | ||
*/ | ||
////////////////////////////// | ||
// set info here | ||
////////////////////////////// | ||
|
||
|
||
// GitHub repository information | ||
const owner = 'cmip-ipo-internal'; | ||
const repo = 'CVTool'; | ||
const githubToken = '******'; // Replace with your GitHub personal access token | ||
const airtablename = 'cvtooltable' | ||
|
||
const maintainors = {'Daniel Ellis':'wolfiex',}; | ||
|
||
|
||
////////////////////////////// | ||
// gets the data from form | ||
////////////////////////////// | ||
|
||
let template; | ||
const inputCode = input.get("") | ||
// const table = base.getTable(airtablename); | ||
|
||
// Regular expression patterns to extract key-value pairs | ||
const keyValuePattern = /<b>(.*?)<\/b><br\/>(.*?)<br\/><br\/><br\/>/g; | ||
const keyPattern = /<b>(.*?)<\/b><br\/>/; | ||
const valuePattern = /<br\/>(.*?)<br\/><br\/><br\/>/; | ||
|
||
// Initialize an object to store key-value pairs | ||
const result = {}; | ||
|
||
// Extract key-value pairs using regular expressions | ||
let match; | ||
while ((match = keyValuePattern.exec(inputCode)) !== null) { | ||
const keyMatch = keyPattern.exec(match[0]); | ||
const valueMatch = valuePattern.exec(match[0]); | ||
|
||
if (keyMatch && valueMatch) { | ||
const key = keyMatch[1]; | ||
const value = valueMatch[1]; | ||
result[key] = value.replace(/<[^>]*>/g, ''); | ||
} | ||
} | ||
|
||
|
||
|
||
////////////////////////////// | ||
// Log the resulting JSON object | ||
|
||
|
||
result['Assign'] = result['Assign'].split('- ') | ||
result['Label'] = result['Label'].split('- ').filter(d=>d) | ||
|
||
result['Assign'] = result['Assign'].map(d=>maintainors[d]).filter(d=>d) | ||
|
||
|
||
////////////////////////////// | ||
|
||
template = ` | ||
--- | ||
# 🚀 ${result['Title']} 🚀 | ||
--- | ||
**Issuer**: ${'@'+ (result['Github'] || result['Email'].split('@')[0])} | ||
**Related Issues**: | ||
${JSON.stringify(result['Related'])||''} | ||
**Description**: | ||
${result['Description']} | ||
**Steps to Reproduce** (if applicable): | ||
${JSON.stringify(result['Reproduce'])||''} | ||
**Expected Behavior**: | ||
${JSON.stringify(result['Expected'])||'none'} | ||
--- | ||
` | ||
|
||
|
||
////////////////////////////// | ||
// Submit github | ||
////////////////////////////// | ||
|
||
// Create a new GitHub issue | ||
const url = `https://api.github.com/repos/${owner}/${repo}/issues`; | ||
|
||
const requestBody = { | ||
title: result['Title'], | ||
body: template, | ||
}; | ||
|
||
if (result['Label']) requestBody['labels'] = result['Label'] | ||
if (result['Assign']) requestBody['Assign'] = result['Assign'] | ||
|
||
|
||
console.log(result) | ||
try { | ||
const response = await fetch(url, { | ||
method: 'POST', | ||
headers: { | ||
'Authorization': `token ${githubToken}`, | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(requestBody), | ||
}); | ||
if (response.status === 401) { | ||
console.log('no write on the token'); | ||
} | ||
if (response.status === 201) { | ||
console.log('GitHub issue created successfully.'); | ||
} else { | ||
console.error('Failed to create GitHub issue.',response); | ||
} | ||
} catch (error) { | ||
console.error('Error creating GitHub issue:', error); | ||
} | ||
``` |
Oops, something went wrong.