Creazione di dashboard live con Airtable e React

Pubblicato: 2022-03-11

Indipendentemente dal fatto che un'azienda sia una grande impresa o una startup in erba, la raccolta di dati da utenti e clienti e il reporting o la visualizzazione di tali dati sono fondamentali per l'azienda.

Di recente ho lavorato con una startup di telemedicina con sede in Brasile. La sua missione è fornire assistenza e monitoraggio a distanza collegando i pazienti a professionisti medici e allenatori sanitari. L'esigenza principale era creare un'interfaccia per gli allenatori e gli operatori sanitari per rivedere facilmente le informazioni di un paziente e le metriche più importanti relative alla loro situazione particolare: una dashboard.

Inserisci Typeform e Airtable.

Forma tipografica

Typeform è uno degli strumenti di raccolta dati di riferimento che consente esperienze Web reattive per gli utenti che completano un sondaggio. Inoltre viene fornito con diverse funzionalità che rendono i sondaggi più intelligenti, soprattutto se combinati:

  • Salti logici
  • Campi nascosti

I sondaggi possono essere condivisi tramite URL che possono essere pre-seminati con valori per i campi nascosti, che possono quindi essere utilizzati per implementare salti logici e modificare il comportamento del sondaggio per l'utente con il collegamento.

Usi Airtable

Airtable è un ibrido foglio di calcolo-database e una piattaforma cloud collaborativa. La sua attenzione alla funzionalità punta e clicca significa che gli utenti non tecnici possono configurarla senza codifica. Airtable ha una moltitudine di casi d'uso in qualsiasi azienda o progetto.

Puoi utilizzare una base Airtable per:

  • CRM (gestione delle relazioni con i clienti)
  • HRIS (Sistema Informativo Risorse Umane)
  • Gestione di progetto
  • Pianificazione dei contenuti
  • Pianificazione di eventi
  • Feedback dell'utente

Ci sono molti altri potenziali casi d'uso. Puoi esplorare i casi di studio di Airtable qui.

Se non hai familiarità con Airtable, il modello di dati concettuali si scompone in questo modo:

  • Area di lavoro - Composta da basi
  • Base - Composta da Tavoli
  • Tabella - Composto da Campi (colonne) e righe
  • Visualizza : una prospettiva sui dati della tabella con filtri opzionali e campi ridotti
  • Campo : una colonna di una tabella con un tipo di campo; vedere qui per ulteriori informazioni sui tipi di campo

Oltre a fornire un database ospitato su cloud con funzionalità familiari del foglio di calcolo, ecco alcuni dei motivi per cui la piattaforma è così potente:

Rappresentazione di utenti tecnici e non tecnici che lavorano con Airtable.

Per gli utenti non tecnici, Airtable fornisce:

  • Un'interfaccia front-end facile da usare
  • Automazioni che possono essere create con la configurazione point-and-click per inviare e-mail, elaborare righe di dati, pianificare appuntamenti nei calendari e altro ancora
  • Più tipi di viste che consentono ai team di collaborare sulla stessa base e tabelle
  • App Airtable che possono essere installate dal mercato per potenziare una Base

Per gli sviluppatori, Airtable fornisce:

  • Un'API back-end ben documentata
  • Un ambiente di scripting che consente agli sviluppatori di automatizzare le azioni all'interno di una Base
  • Automazioni che possono anche attivare script sviluppati su misura che vengono eseguiti all'interno dell'ambiente Airtable, estendendo le capacità delle automazioni

Puoi saperne di più su Airtable qui.

Per iniziare: dattilografa in Airtable

I sondaggi Typeform erano già configurati dal cliente e il passaggio successivo è stato pianificare il modo in cui i dati sarebbero atterrati in Airtable e quindi trasformati in un dashboard. Ci sono molte domande da considerare quando si creano dashboard su qualsiasi database: come dovremmo strutturare i dati? Quali dati dovranno essere elaborati prima della visualizzazione? Dovremmo sincronizzare Base con Fogli Google e utilizzare Google Data Studio? Dovremmo esportare e trovare un altro strumento di terze parti?

Fortunatamente per gli sviluppatori, non solo Airtable fornisce automazioni e script per gestire le fasi di elaborazione dei dati, ma ha anche reso possibile creare applicazioni e interfacce personalizzate su una base Airtable con le app Airtable.

App personalizzate in Airtable

Le app personalizzate in Airtable esistono da quando Airtable Blocks SDK è stato rilasciato all'inizio del 2018 e sono state recentemente rinominate in App. Il rilascio di Blocks è stato enorme in quanto significava che i creatori ora avevano la possibilità di sviluppare, come dice Airtable, "Un kit Lego infinitamente ricombinabile".

Più recentemente, con il passaggio alle app, Airtable Marketplace ha reso possibile anche condividere le app pubblicamente.

Le app Airtable forniscono alle aziende un kit Lego infinitamente ricombinabile che possono adattare alle loro esigenze.

Per creare un'app personalizzata in Airtable, uno sviluppatore JavaScript deve sapere come utilizzare React, una delle librerie JavaScript più popolari per la creazione di interfacce utente. Airtable fornisce una libreria di componenti di componenti e hook funzionali di React, che sono di grande aiuto per creare rapidamente un'interfaccia utente coerente e determinare come gestirai lo stato all'interno dell'app e dei suoi componenti.

Consulta l'articolo Introduzione di Airtable per ulteriori informazioni e Airtable su GitHub per esempi di app.

Requisiti del dashboard Airtable

Dopo aver esaminato i modelli di dashboard con il team del cliente, i tipi di dati da utilizzare erano chiari. Avremmo bisogno di una serie di componenti del dashboard che verrebbero visualizzati come testo sul dashboard e grafici di diverse metriche che potrebbero essere monitorate nel tempo.

Coach e professionisti sanitari dovevano essere in grado di creare un dashboard personalizzato per ogni paziente, quindi avevamo bisogno di un modo flessibile per aggiungere e rimuovere i grafici. Verrebbero visualizzati altri dati statici relativi a ciascun paziente, indipendentemente dal paziente selezionato.

In questo caso, le sezioni del dashboard si riducono a:

  • Informazioni generali : nome del paziente, e-mail, numero di telefono, preferenza di contatto, data di nascita, età
  • Obiettivi - Obiettivi che il paziente ha in base ai risultati del sondaggio
  • Alcune statistiche : BMI, altezza e peso
  • Uso di medicinali - Elenco di tutti i farmaci da prescrizione già utilizzati da un paziente
  • Storia familiare di condizioni - Utile nella diagnosi di determinate condizioni
  • Grafici : una sezione in cui l'utente del dashboard di Airtable può aggiungere un grafico e configurare la metrica che visualizzerà nel tempo

Immagine che mostra un mockup di Airtable Dashboard.

Un modo per accedere a tutte le sezioni, ad eccezione dei grafici, sarebbe quello di inserire nel dashboard tutte le colonne relative agli obiettivi, all'uso dei farmaci e alla storia familiare. Tuttavia, ciò non consentirebbe al team del cliente di aggiungere nuove domande a un sondaggio Typeform né di aggiungere una nuova colonna a una tabella Airtable per presentare quei dati sulla dashboard senza che uno sviluppatore aggiorni l'app personalizzata.

Una soluzione più elegante ed estensibile a questa sfida è stata trovare un modo per contrassegnare le colonne come rilevanti per una particolare sezione del dashboard e recuperare quelle colonne utilizzando i metadati che Airtable espone quando si utilizzano i modelli Tabella e Campo.

Ciò è stato ottenuto utilizzando le descrizioni dei campi come posizione per contrassegnare una colonna della tabella come pertinente a una sezione del dashboard da visualizzare all'utente. Quindi, potremmo garantire che solo coloro con il ruolo di Creatore (gli amministratori) per la Base avessero la possibilità di modificare queste Descrizioni dei campi per alterare ciò che appare sul dashboard. Per illustrare questa soluzione, ci concentreremo principalmente sugli elementi in Informazioni generali e su come presentare i grafici.

Creazione di un sistema #TAG#

Date le sezioni del dashboard, aveva senso creare tag riutilizzabili per alcune sezioni e tag specifici per determinate colonne. Per elementi come il nome del paziente, l'e-mail e il numero di telefono, #NAME# , #EMAIL# e #PHONE# sono stati aggiunti rispettivamente alla descrizione di ciascun campo. Ciò consentirebbe di recuperare tali informazioni tramite i metadati della tabella in questo modo:

 const name = table ? table.fields.filter(field => field.description?.includes("#NAME#"))

Per le aree della dashboard che avrebbero bisogno di attingere da molte colonne contrassegnate, avremmo i seguenti tag per ciascuna sezione della dashboard:

  • OBJ - Obiettivi
  • FAM - Storia familiare
  • MED - Uso della medicina
  • CAN - Storia familiare specifica del cancro
  • CHART - Qualsiasi colonna che dovrebbe essere originata per l'aggiunta di grafici; deve essere una quantità

Inoltre, era importante separare il nome di una colonna in una tabella dall'etichetta che avrebbe ricevuto sulla dashboard, quindi qualsiasi cosa che avesse ricevuto un #TAG# avrebbe anche la possibilità di ricevere due tag #LABEL# nella sua Descrizione del campo . Una descrizione del campo sarebbe simile a questa:

Screenshot che mostra l'uso dei tag nella descrizione di un campo.

Nel caso in cui manchino i tag #LABEL# , visualizzeremo il nome della colonna dalla tabella.

Possiamo analizzare l'etichetta impostata nella descrizione con una semplice funzione come questa dopo aver recuperato il campo con l'esempio di codice precedente:

 // utils.js export const setLabel = (field, labelTag = "#LABEL#") => { const labelTags = (field.description?.match(new RegExp(labelTag, "g")) || []).length; let label; if (labelTags === 2) label = field.description?.split(`${labelTag}`)[1]; if (!label || label?.trim() === '') label = field.name; return {...field, label, name: field.name, description: field.description}; }

Con questo sistema #TAG# raggiungiamo tre obiettivi principali:

  • I nomi delle colonne (campi) nella tabella possono essere modificati come desiderato.
  • Le etichette per i dati nel dashboard possono essere distinte dai nomi delle colonne.
  • Le sezioni del dashboard per obiettivi, utilizzo dei farmaci, storia familiare e grafici possono essere aggiornate dal team del cliente senza toccare una riga di codice.

Stato persistente in Airtable

In React, utilizziamo lo stato e lo passiamo ai componenti come oggetti di scena per eseguire nuovamente il rendering di quel componente se il suo stato cambia. Normalmente questo è legato a una chiamata API che alimenta un componente del dashboard, ma in Airtable abbiamo già tutti i dati e dobbiamo semplicemente filtrare ciò che stiamo visualizzando in base al paziente che stiamo visualizzando. Inoltre, se utilizziamo lo stato, non manterrà i dati dopo un aggiornamento nella dashboard stessa.

Quindi, come possiamo mantenere un valore dopo l'aggiornamento per mantenere un dashboard filtrato? Fortunatamente, Airtable fornisce un hook per questo chiamato useGlobalConfig in cui mantiene un archivio chiave-valore per l'installazione di un'app su un dashboard. Dobbiamo semplicemente implementare la logica di recupero dei valori da questo archivio di valori-chiave quando l'app viene caricata per alimentare i componenti della dashboard.

Ciò che è ancora più utile nell'uso useGlobalConfig è che quando i suoi valori sono impostati, il componente dashboard e i suoi componenti figlio vengono nuovamente visualizzati, quindi puoi usare Global Config come faresti con una variabile di stato in una tipica implementazione di React.

Presentazione dei grafici

Airtable fornisce esempi di grafici con la sua app Simple Chart, che utilizza React Charts, un wrapper React su Chart.js (chart-ception).

Nell'app Simple Chart, abbiamo un grafico per l'intera app, ma nella nostra app Dashboard, abbiamo bisogno della possibilità per l'utente di aggiungere e rimuovere i propri grafici dal proprio dashboard. Inoltre, nella discussione con il team del cliente, sembra che alcune metriche sarebbero meglio visualizzate sullo stesso grafico (come le letture della pressione diastolica e sistolica).

Con questo abbiamo i seguenti elementi da affrontare:

  • Stato persistente per il grafico di ogni utente (o ancora meglio usando Global Config)
  • Consentire più metriche per grafico

È qui che la potenza della configurazione globale torna utile, poiché possiamo utilizzare l'archivio valori-chiave per mantenere le metriche selezionate e qualsiasi altra cosa sul nostro elenco di grafici. Quando configuriamo un grafico nell'interfaccia utente, il componente grafico stesso verrà rieseguito a causa degli aggiornamenti alla configurazione globale. Per la sezione dei grafici della dashboard, ecco un'idea con i componenti di riferimento, concentrandosi su dashboard charts.js e single chart.js.

La tabella passata a ciascun grafico è ciò che viene utilizzato per i suoi metadati per trovare i campi, mentre i record passati sono già stati filtrati dal paziente selezionato nel componente dashboard di primo livello che importa dashboard_charts/index.js .

Nota che i campi elencati come opzioni nel menu a discesa di un grafico vengono estratti utilizzando il tag #CHART# menzionato prima, con questa riga in un hook useEffect :

 // single_chart/index.js … useEffect(() => { (async () => { ... if (table) { const tempFieldOptions = table.fields.filter(field => field.description?.includes('#CHART#')).map(field => { return { ...setLabel(field), value: field.id } }); setFieldSelectOptions([...tempFieldOptions]); } })(); }, [table, records, fields]); ...

Il codice sopra mostra come la funzione setLabel a cui si fa riferimento in precedenza viene utilizzata con #TAG# per aggiungere qualsiasi cosa fornita nei tag #LABEL# e visualizzarla per l'opzione nel campo a discesa.

Il nostro componente grafico sfrutta le capacità multiasse fornite da Chart.js, che viene mostrato con React Charts. L'abbiamo appena esteso tramite l'interfaccia utente con la possibilità dell'utente di aggiungere un set di dati e un tipo di grafico (linea o barra).

La chiave per usare Global Config, in questo caso, è sapere che ogni chiave può contenere solo una stringa | booleano | numero | nullo | GlobalConfigArray | GlobalConfigObject (consultare il riferimento al valore di configurazione globale).

Abbiamo i seguenti elementi da mantenere per grafico:

  • chartTitle che viene generato automaticamente e può essere rinominato dall'utente
  • array di campi in cui ogni elemento ha:
    • campo come fieldId da Airtable
    • chartOption come una riga | barra come indicano i documenti Chart.js
    • color come il colore Airtable da colorUtils
    • hex come codice esadecimale relativo al colore Airtable

Per gestirlo, ho trovato più conveniente stringere questi dati come un oggetto invece di impostare chiavi e valori di configurazione globale fino in fondo. Vedere l'esempio seguente (globalConfig.json nel gist), che include i valori di configurazione globale per filtrare i record in base al paziente e alcune variabili correlate utilizzate per supportare un componente di filtraggio typeahead (grazie a react-bootstrap-typeahead):

 { "xCharts": { "chart-1605425876029": "{\"fields\":[{\"field\":\"fldxLfpjdmYeDOhXT\",\"chartOption\":\"line\",\"color\":\"blueBright\",\"hex\":\"#2d7ff9\"},{\"field\":\"fldqwG8iFazZD5CLH\",\"chartOption\":\"line\",\"color\":\"blueLight1\",\"hex\":\"#9cc7ff\"}],\"chartTitle\":\"Grafico criado em 11/15/2020, 2:37:56 AM\"}", "chart-1605425876288": "{\"fields\":[{\"field\":\"fldGJZIdRlq3V3cKu\",\"chartOption\":\"line\",\"color\":\"blue\",\"hex\":\"#1283da\"}],\"chartTitle\":\"Grafico criado em 11/15/2020, 2:37:56 AM\"}", "chart-1605425876615": "{\"fields\":[{\"field\":\"fld1AnNcfvXm8DiNs\",\"chartOption\":\"line\",\"color\":\"blueLight1\",\"hex\":\"#9cc7ff\"},{\"field\":\"fldryX5N6vUYWbdzy\",\"chartOption\":\"line\",\"color\":\"blueDark1\",\"hex\":\"#2750ae\"}],\"chartTitle\":\"Grafico criado em 11/15/2020, 2:37:56 AM\"}", "chart-1605425994036": "{\"fields\":[{\"field\":\"fld9ak8Ja6DPweMdJ\",\"chartOption\":\"line\",\"color\":\"blueLight2\",\"hex\":\"#cfdfff\"},{\"field\":\"fldxVgXdZSECMVEj6\",\"chartOption\":\"line\",\"color\":\"blue\",\"hex\":\"#1283da\"}],\"chartTitle\":\"Grafico criado em 11/15/2020, 2:39:54 AM\"}", "chart-1605430015978": "{\"fields\":[{\"field\":\"fldwdMJkmEGFFSqMy\",\"chartOption\":\"line\",\"color\":\"blue\",\"hex\":\"#1283da\"},{\"field\":\"fldqwG8iFazZD5CLH\",\"chartOption\":\"line\",\"color\":\"blueLight1\",\"hex\":\"#9cc7ff\"}],\"chartTitle\":\"New Chart\"}", "chart-1605430916029": "{\"fields\":[{\"field\":\"fldCuf3I2V027YAWL\",\"chartOption\":\"line\",\"color\":\"blueLight1\",\"hex\":\"#9cc7ff\"},{\"field\":\"fldBJjtRkWUTuUf60\",\"chartOption\":\"line\",\"color\":\"blueDark1\",\"hex\":\"#2750ae\"}],\"chartTitle\":\"Grafico criado em 11/15/2020, 4:01:56 AM\"}", "chart-1605431704374": "{\"fields\":[{\"field\":\"fld7oBtl3iiHNHqoJ\",\"chartOption\":\"line\",\"color\":\"blue\",\"hex\":\"#1283da\"}],\"chartTitle\":\"Grafico criado em 11/15/2020, 4:15:04 AM\"}" }, "xPatientEmail": "[email protected]", "xTypeaheadValue": "Elle Gold ([email protected])", "xSelectedValue": "[{\"label\":\"Elle Gold ([email protected])\",\"id\":\"[email protected]\",\"name\":\"Elle Gold\",\"email\":\"[email protected]\"}]" }

Nota: tutti i dati contenuti sopra e i dati inclusi nelle animazioni seguenti non sono dati reali del paziente.

Ecco uno sguardo al risultato finale:

Visualizzazione animata dell'interfaccia utente del dashboard di Airtable.

Che dire del Typeahead?

Per filtrare per paziente, avevamo bisogno di un modo per selezionare un paziente e quindi filtrare i record in base a questo paziente. In questa sezione, esaminiamo come ciò è stato ottenuto.

Per il typeahead, react-bootstrap-typeahead è stata una scelta facile, poiché gli unici passaggi rimasti erano preparare le opzioni per il typeahead, mescolarlo con un input Airtable per lo styling e il caricamento del bootstrap e alcuni altri stili per il nostro menu. Rilasciare i componenti dalle tue librerie di componenti preferite in un'app Airtable non è così semplice come nel tipico sviluppo web di React; tuttavia, ci sono solo alcuni passaggi aggiuntivi per far sì che tutto appaia come ti aspetteresti.

Questo è il risultato finale:

GIF animata che mostra la funzionalità filtro per paziente.

Per rendere l'input di Airtable e mantenere tutti i nostri stili coerenti, react-bootstrap-typeahead viene fornito con un prop renderInput. Vedi di più su come modificare il rendering del componente qui.

Per gli stili bootstrap e per sovrascrivere le nostre voci di menu, sono state utilizzate le seguenti due utilità da Airtable:

  • loadCSSFromString
  • loadCSSFromURLAsync

Vedi frontend.js nel gist per un estratto dell'implementazione typeahead.

Questa riga è stata utilizzata per caricare bootstrap a livello globale:

 // frontend/index.js loadCSSFromURLAsync('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css');

Noterai una logica aggiuntiva per cose come la gestione delle modifiche di stile al passaggio del mouse o il restyling dei collegamenti ( <a></a> ) per ottenere l'aspetto e la sensazione familiari del bootstrap. Ciò include anche la gestione dell'impostazione dei valori di configurazione globale per il typeahead e il filtraggio dei record in modo che se un utente lascia la dashboard, aggiorna la propria pagina o desidera condividere questa dashboard con altri, l'app mantiene il paziente selezionato nella dashboard App. Ciò consente inoltre agli utenti di installare più copie della stessa app affiancate nella stessa dashboard Airtable con diversi pazienti selezionati o con grafici diversi.

Tieni presente che una dashboard in Airtable è disponibile anche per tutti gli utenti della Base, quindi queste installazioni di app personalizzate su una dashboard verranno filtrate per gli stessi pazienti e grafici, indipendentemente dagli utenti che stanno guardando la dashboard contemporaneamente.

Ricapitoliamo ciò di cui abbiamo parlato finora:

  1. Airtable consente sia agli utenti non tecnici che agli utenti tecnici di collaborare in Airtable.
  2. Typeform viene fornito con un'integrazione Airtable che consente agli utenti non tecnici di mappare i risultati di Typeform su Airtable.
  3. Le app Airtable forniscono un modo efficace per potenziare la sua base Airtable, sia selezionando dal mercato o creando un'app personalizzata.
  4. Gli sviluppatori possono estendere Airtable rapidamente in quasi tutti i modi immaginabili con queste app. Il nostro esempio sopra ha richiesto solo tre settimane per essere progettato e implementato (con l'enorme aiuto delle biblioteche esistenti, ovviamente).
  5. Un sistema #TAG# può essere utilizzato per modificare la dashboard senza richiedere modifiche al codice da parte degli sviluppatori. Ci sono casi d'uso migliori e peggiori per questo. Assicurati di limitare le autorizzazioni al ruolo Creator se utilizzi questa strategia.
  6. L'uso di Global Config consente agli sviluppatori di mantenere i dati all'interno di un'installazione di app. Combina questo nella tua strategia di gestione dello stato per eseguire il seeding dei dati per i tuoi componenti.
  7. Non aspettarti di trascinare e rilasciare componenti da altre librerie e progetti direttamente nella tua app Airtable. Gli stili possono essere caricati utilizzando le loadCSSFromString e loadCSSFromURLAsync fornite da Airtable.

A prova di futuro

Utilizzare un middleware più sofisticato

Con Typeform e Airtable, è facile ed economico configurare la mappatura delle domande alle colonne.

Tuttavia, c'è un grosso inconveniente: se hai un sondaggio con più di 100 domande mappate su Airtable e devi modificare una mappatura, devi eliminare l'intera mappatura e ricominciare. Questo chiaramente non è l'ideale, ma per un'integrazione gratuita, possiamo affrontarlo.

Altre opzioni sarebbero avere un'integrazione Zapier (o simile) per gestire i dati tra Typeform e Airtable. Quindi potresti modificare la mappatura di qualsiasi domanda su qualsiasi colonna senza ricominciare da zero. Ciò avrebbe anche le sue considerazioni sui costi da tenere in considerazione.

Si spera che alcune delle lezioni apprese e comunicate qui aiutino gli altri che stanno cercando di creare soluzioni con Airtable.

Infine, puoi controllare l'essenza con i file discussi in questo articolo.