Here's a project I worked on for a customer to build a DDX Brick that acts as a Landing Page that only shows pages the user has access to.
Special thanks to Jace M from @DomoHQ for sharing this template with me and @noahfinberg7364 for all his help teaching me DDX things!
DDX GitHub Repo -- code lives here
DomoLibrary Repo -- python library I used to build the dataset powering the brick.
https://github.com/jaewilson07/domo_l...
Support my work - https://venmo.com/jaemyong-wilson
I'm sponsored by Argo Analytics
If you need help with custom apps, talk to the guys over at Argo Analytics
Join our 🧵 Domo User Group Slack
A Quick Code Review.
Although the code does flow top to bottom, notice that there are no clear boundaries to the code. You can't really parameterize it easily, and the original code certainly can't recycle code blocks.
In this original code snippet domo.get() is an asynchronous function, whose result (data) will be passed directly into handleResult() which both shapes the data into a usable form (a list of dictionaries) and then paints the app.
While it is nice to just have one long function, it's tough to troubleshoot or swap in new code.
var domo = window.domo;
var datasets = window.datasets;
var Query = window.Query;
// HTML Bootstrap Grid Configuration
var query = (new Query())
.select('Logo', 'Text', 'URL', 'Order')
.orderBy('Order', 'Ascending')
.query(datasets[0]);
domo.get(query, {format: 'array-of-arrays'}).then(handleResult);
// Loop through result to build out grid
function handleResult(data) {
// Restructure the array-of-arrays object into a usable object
const rows = data.rows.map(row => {
return data.columns.reduce((acc, curr, index) => {
acc[curr] = row[index];
return acc;
}, {});
});
// Loop through rows to create the grid objects
let container = document.getElementById("grid");
let counter = 1
rows.forEach(row => (...paint my app ...))
Below, we've rewritten it a series of async functions where all the calls are in main().
Notice that get_data receives the dataset and Query class and then returns a processed dataset (the FOR LOOP has been integrated into get_data()).
async function get_data(dataset, Query) {
// HTML Bootstrap Grid Configuration
const query = new Query()
.select('Logo', 'Text', 'URL', 'Order')
.orderBy('Order', 'Ascending')
.query(dataset);
data = await domo.get(query, { format: 'array-of-arrays' });
return data.rows.map((row) => {
return data.columns.reduce((acc, curr, index) => {
acc[curr] = row[index];
return acc;
}, {});
});
}
async function main(window) {
var domo = window.domo;
data = await get_data( dataset = window.datasets[0], Query = window.Query);
... paint my app ...
}
I preferred a different endpoint for retrieving data, so I wrote get_data_v2, commented out the line in main() and added a new one.
async function get_data_v2(dataset, userEmail) {
data = await domo.post( `/sql/v1/${dataset}`,
`SELECT * FROM ${dataset} WHERE lower(user_email) = '${userEmail}' and parent_page_title is null`,
{ contentType: 'text/plain' }
);
return data.rows.map((row) => {
return data.columns.reduce((acc, curr, index) => {
acc[curr] = row[index];
return acc;
}, {});
});
}
async function main(window) {
var domo = window.domo;
// data = await get_data( dataset = window.datasets[0], Query = window.Query);
data = await get_data_v2(dataset = window.datasets[0], userEmail.toLowerCase());
... paint my app ...
}
Hope this helps!


