Jae Wilson @DataCrew
Domo

Build a DDX Brick for a User Landing Page

May 18, 2023

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 herehttps://github.com/jaewilson07/datacr...

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!

Related

More posts on similar topics.

Got a project in mind?

hire me →

Getting value from the content but not ready to hire?

let's call it professional development

☕ buy me a coffee →

Want a practitioner take on Domo and AI, every month?

free, no spam, unsubscribe anytime

📰 subscribe to the digest →