Skip to content

Instantly share code, notes, and snippets.


Adam Morris brainysmurf

View GitHub Profile
brainysmurf / tests.js
Last active Oct 24, 2021
Use from within Postman as visualizer
View tests.js
* Get an overview table of all items returned from the endpoint, useful for when there lists of objects are returned.
* See comments below for screenshots.
* To use, copy the below code into the "Tests" tab of the endpoint
* Click blue "Send" button
* Click on "Visualize" in the Body tile
* Note that it only displays the returned objects, there's nothing magical that's getting "all" objects via pagination
brainysmurf /
Last active Oct 6, 2021
Data flow mini share: OpenApply -> Google Sheets -> Google Data Studio

Data Flow mini share: OA > GSheet > GDS

In this tutorial, we'll use OpenApply as the source of truth to store extra information about each student, connect it via automatic updates to a Google Spreadsheet, and then connect it to Google Data Studio as a data source.

This solution if for a use case where there is a data point for each student, such as consent to be photographed, that needs to be retrieved occassionally by practitioners. It uses OA's custom fields, a tool that downloads and incrementally updates to a Google Spreadsheet, which is then used as a data connector to a Data Studio project.

Schools can then embed the graphs with filtering and search capability into a Google Site to surface the tool. They will then be able to look up this information.

Setup the data source spreadsheet


FEB Virtual Community: Visualizations

Please find attached!

brainysmurf / snippet.js
Last active Jul 9, 2021
outputSheet snippet
View snippet.js
* Append a 2d array to an existing sheet or can create a new sheet
* to match the largest row in the dataset.
* @param {array} data 2d array of data
* @param {string} sheetName (optional) The sheet you want to output to. If the sheet does not exist, this script will auto-create a new sheet with the specified sheet name. If the sheetName is not specified, a new sheet will be created
function outputToSheet(data, sheetName=null) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
if (sheetName==null) sheetName = 'Default Sheet Name';
brainysmurf /
Last active Jun 22, 2021
Performance of Endpoins library using fetch requests compared to advanced service.


After a few months of using my Endpoints library to help solve myriad of problems in production, I've only had anecdotal evidence that it was a "way more" performant way of interacting with API endpoints, compared to more traditional method of using AppsScripts advanced services. So I decided to actually measure it.

The Test

In my domain, there are 26 google groups, a set for each grade in the school, where a set is one for students and one for parents. We have about 30 students per grade, which means membership of the each students group is about 30, but for the parents, it is twice that (as both parents are a member).

With two different code bases, I download all memberships of all these groups.

brainysmurf /
Last active Jun 19, 2021
An `onEdit` trigger that ensures that only one checkbox is selected in a row. Set up once and will work even with changes to name of the sheet, or where it is in terms of rows and columns. Motivated from

This onEdit trigger implements the feature as given by Ben Collins.

I was motivated to see if the pattern as given by Ben could be abstracted away so that changes to the sheet name, or changes to the area of the checkboxes changed, and the onEdit trigger wouldn't need to be modified.

Sheet1 tab:

For example, clicking on D1 should change it to checked (X), and uncheck B1.

| | A | B | C | D | E |

brainysmurf /
Last active Jun 6, 2021
Performance of various iterations in AppsScripts
function measure_({func, arr}) {
const start = new Date().getTime();, arr);
const end = new Date().getTime();
const delta = end - start;
const report = `${} took ${delta} milliseconds`;
return delta;
brainysmurf /
Last active Jun 10, 2021
Timetabling with aSc and ManageBac

Timetabling with aSc and ManageBac

This gist will explain how I built a schedule with aSc timetables, and used the exported XML data to turn it into CSVs compatible with ManageBac's bulk imports for classes and timetable uploads.

This is not intended to provide a complete end-to-end solution, but to provide timetablers with general strategies with specific examples. In particular, the use of aSc subjects and divisions, how they should coincide with complex scheduling needs, and then how to get it to a "flat" output for csv upload. There are a variety of ways to specify a timetable with aSc; this solution only uses constraints provided by subject and division specifications.

This example uses a 7-Day Timetable (Day 1, Day 2, … Day 7), where each day has four blocks (Block 1, Block 2, … Block 4), and each block can be divided into two periods. (Block 1 consists of periods 1 and 2, Block 4 consists of periods 7 and 8). There are seven subjects, plus some school-specific subj

* This is my version of what I embed into libraries I want to track, as cluster.
* This way it ensures that consistent name, version used throughout, and easy to define namespace
* Note use of "name" "space" parameters
function TrackMyself ({name='dottie', space=null, version='v1.5', ...kwargs}={}) {
if (Object.keys(kwargs).length>0) throw new TypeError("Unexpected param received");
const track = cttLibTracker.TrackMyself;
const options = {
brainysmurf /
Last active May 3, 2021
Extending classes in Libraries with AppsScripts

A question on an #AppsScripts user forum led me into an investigation into the best way to extend a class, for example a Date class, from inside a library so that the host project can use it.

Let's suppose we want to make a class BetterDate that extends the date object so that it automatically calculates the result of .getTime() once. (Maybe we don't want to waste time? rimshot)

We'll add an instance method on it to calculate how many days we have to wait (until our birthday). We also need a static object now() on it so that we can get a now date that is an instance of BetterDate.

This to me is most elegant:

// lib code