Utiliser des composants de visualisation pour créer une visualisation personnalisée

Ce tutoriel s'adresse aux développeurs JavaScript expérimentés et suppose une certaine connaissance des techniques de programmation fonctionnelles.

Dans cet exemple, nous commençons par une requête liée à des informations de ventes trimestrielles hypothétiques pour certaines marques. Nous allons commencer par filtrer la requête pour des marques spécifiques, puis faire pivoter les résultats par trimestre pour les ventes. Vous trouverez un exemple dans le tableau suivant.

Résultats d'une requête sur le nombre de commandes par marque, avec un changement de dimension pour la dimension Trimestres des créations.

Ensuite, nous allons utiliser des composants de visualisation pour créer une visualisation personnalisée qui illustre les tendances de chaque marque au cours du dernier trimestre. Vous obtenez un nouveau type de visualisation qui se compose d'une série de sparklines imbriquées dans une table, comme dans l'exemple suivant:

Visualisation personnalisée affichant un tableau avec une ligne pour chaque marque, et une ligne sparkline intégrée affichant les commandes par trimestre sur chaque ligne.

En plus de vous montrer comment créer une visualisation personnalisée, cet exemple présente quelques bonnes pratiques pour utiliser l'API Looker dans une application React.

Pour créer une visualisation personnalisée avec des composants Looker, assurez-vous que votre configuration respecte les exigences, puis procédez comme suit:

  1. Créer une requête dans un fichier Explorer et copier la valeur qid
  2. Transmettre les données à un composant de visualisation personnalisé
  3. Créer le composant CustomVis
  4. Transformer les données normalisées
  5. Insérer les données transformées dans CustomVis
  6. Générer la visualisation personnalisée

L'utilisation de composants de visualisation pour créer une visualisation personnalisée est appropriée lorsque cette visualisation est destinée à une application ou une extension intégrée. Si vous souhaitez rendre la visualisation personnalisée disponible pour les utilisateurs de Looker sur une instance Looker, suivez les instructions de la page de documentation visualization. Si vous souhaitez développer une visualisation personnalisée et l'importer sur Looker Marketplace, suivez les instructions de la page Développer une visualisation personnalisée pour Looker Marketplace.

Conditions requises

Avant de commencer, vous devez disposer de certains éléments:

  • Vous devez avoir accès à une instance Looker.
  • Que vous compiliez le framework d'extension ou votre propre application React autonome, il est important de vous authentifier auprès de l'API de Looker et d'avoir accès à l'objet SDK Looker. Pour en savoir plus, consultez Authentification de l'API Looker ou notre framework d'extensions.
  • Vérifiez que vous avez installé le package NPM des composants de visualisation Looker, ainsi que le package NPM @looker/components-data. Vous trouverez des informations sur l'installation et l'utilisation du package de composants de visualisation dans le document README, disponible sur GitHub et NPM.

Étape 1: Créez une requête dans Explorer et copiez l'ID de requête

Dans cet exemple, nous utilisons des informations de ventes trimestrielles pour les marques que nous suivons au fil du temps.

Nous allons ponter ces données, car Looker permet de regrouper les résultats de la requête dans un tableau croisé dynamique. Dans Explorer, nous pouvons exécuter une requête et créer un graphique des données à l'aide de l'un des types de visualisation native de Looker. Le graphique fournit de nombreuses informations, mais il est difficile d'analyser d'un coup d'œil la tendance des produits de chaque marque:

Graphique généré à partir d'une requête sur le nombre de commandes par marque, avec un tableau croisé dynamique basé sur la dimension Trimestres créés

Comme pour l'exemple de rendu simple, l'étape suivante consiste à copier la valeur qid à partir de la barre d'adresse URL de l'exploration. Pour les besoins de cet exemple, la valeur qid est Uijcav7pCA4MZY2MompsPZ, mais elle est spécifique à notre instance de test.

Étape 2: Transmettre les données à un composant de visualisation personnalisé

Pour commencer, transmettez la valeur qid issue de l'URL de l'exploration au composant Query, puis l'objet SDK authentifié à DataProvider.

import React, { useContext } from 'react'
import { ExtensionContext } from '@looker/extension-sdk-react'
import { DataProvider } from '@looker/components-data'
import { Query } from '@looker/visualizations'

export const MyReactApp = () => {
  const { core40SDK } = useContext(ExtensionContext)

  return (
    <DataProvider sdk={core40SDK}>
      <Query query='Uijcav7pCA4MZY2MompsPZ'></Query>
    </DataProvider>
  )
}

Ensuite, au lieu d'afficher une visualisation Looker native via le composant Visualization, nous allons créer notre propre composant personnalisé appelé CustomVis.

Le composant Query peut accepter n'importe quel élément React en tant qu'enfant et transmet simplement les valeurs config, data, fields et totals en tant que propriétés pour afficher vos propres composants de visualisation. Nous afficherons CustomVis en tant qu'enfant de Query afin qu'il puisse recevoir toutes les données pertinentes en tant que propriétés.

import React, { useContext } from 'react'
import { ExtensionContext } from '@looker/extension-sdk-react'
import { DataProvider } from '@looker/components-data'
import { Query } from '@looker/visualizations'
import { CustomVis } from '../path/to/MyCustomVis'

export const MyReactApp = () => {
  const { core40SDK } = useContext(ExtensionContext)

  return (
    <DataProvider sdk={core40SDK}>
      <Query query='Uijcav7pCA4MZY2MompsPZ'>
        <CustomVis />
      </Query>
    </DataProvider>
  )
}

Étape 3: Créez le composant CustomVis

Créons maintenant le composant CustomVis. Les propriétés héritées du composant Query sont config, fields, data, pivots et totals:

  • config décrit toutes les conditions d'affichage des données dans un graphique, telles que l'épaisseur de la courbe d'une ligne Spark, ou la taille et la forme des points d'un nuage de points.
  • fields stocke des métadonnées supplémentaires sur les valeurs de mesure et de dimension renvoyées par la requête, telles que le format des valeurs ou les libellés à chaque axe.
  • data est la réponse clé-valeur renvoyée par la requête.
  • pivots décrit la dimension avec laquelle la requête est croisée.
  • totals fait référence aux totals de ligne de Looker à utiliser dans les visualisations basées sur des tables.

Nous pouvons transmettre ces propriétés non modifiées à une visualisation de la table en insérant un composant Table.

import React from 'react'
import { Table } from '@looker/visualizations'

export const CustomVis = ({ config, fields, data, pivots }) => {
  return <Table config={config} data={data} fields={fields} pivots={pivots} />
}

Cela nous donne une idée des données telles qu'elles sont renvoyées directement par le SDK. Dans la réponse affichée, une ligne s'affiche pour chaque marque, avec des résultats regroupés ou croisés par trimestre.

Étape 4: Transformez les données normalisées

Pour convertir ces données croisées afin de les afficher avec des sparklines imbriquées, nous isolons toutes les valeurs de mesure et nous les transmettons aux sous-graphiques. Dans le graphique suivant, les données pertinentes pour une seule ligne sont mises en évidence pour illustrer les données que nous allons réduire et afficher avec une visualisation enfant:

Graphique des résultats de données, avec le nombre de commandes sur la deuxième ligne encadré

Nous allons créer une transformation personnalisée pour cela. L'exemple suivant est spécifique à ce scénario. Vous devez analyser vos propres données en conséquence.


import React from 'react'
import { Table, Sparkline } from '@looker/visualizations'

// we assign this value to a constant to ensure that fields and data
// objects remain in sync.
const NESTED_DATA_KEY = 'orderCount'

const nestSparklines = (data) => {
  return data.reduce((acc, d) => {
    // the first entry is the dimension (brand name), and the rest of the rows are the
    // quarterly sales information we want to pass to the Sparkline.
    const [parentDimension, ...measurePairs] = Object.entries(d)

    // `nonPivotedData` represents a single data row.
    // e.g. [{entry: 1, orderCount: 10}, {entry: 2, orderCount: 15}, ...etc]
    const nonPivotedData: SDKRecord[] = measurePairs.map(([_, value], i) => {
      return { entry: i, [NESTED_DATA_KEY]: value }
    })

    // now for each row in the table we render a Sparkline using the `nonPivotedData`
    // that we built above.
    // E.G. [{products.brand: 'adidas', orderCount: <Sparkline />}]
    return [
      ...acc,
      {
        [parentDimension[0]]: parentDimension[1],
        [NESTED_DATA_KEY]: () => (
          <Sparkline
            height={75}
            data={nonPivotedData}
            fields={{
              measures: [{ name: NESTED_DATA_KEY }],
              dimensions: [],
            }}
          />
        ),
      },
    ]
  }, [])
}

Pour créer cette fonction, procédez comme suit:

  1. Réduisez l'ensemble de données afin d'isoler le nom de la marque des données de commande trimestrielles de chaque ligne.
  2. Mettez à jour chaque ligne pour inclure la dimension et un composant React affiché qui peut représenter les valeurs de chaque ligne du tableau.

Étape 5: Insérez les données transformées dans CustomVis

Transformez maintenant les données à l'aide de notre nouvelle fonction et affectez le résultat à une nouvelle variable appelée nestedData:


export const CustomVis =({
  fields,
  data,
  config,
  pivots,
}) => {
  const nestedData = nestSparklines(data)

  return (
    <Table
      fields={{
        measures: [{ name: NESTED_DATA_KEY, label: 'Orders Count By Quarter' }],
        dimensions: fields.dimensions,
        pivots: [],
      }}
      config={config}
      data={nestedData}
      pivots={pivots}
    />
  )
}

Étape 6: Générez la visualisation personnalisée

Une fois les données transformées insérées et configurées, la visualisation ressemble à cet exemple de tableau avec des graphiques sparkline individuels pour chaque ligne:

Visualisation personnalisée affichant un tableau avec une ligne pour chaque marque, et une ligne sparkline intégrée affichant les commandes par trimestre sur chaque ligne.

L'intégralité du code nécessaire pour afficher la visualisation ci-dessus est la suivante:


import React, { useContext } from 'react'
import { ExtensionContext } from '@looker/extension-sdk-react'
import { DataProvider } from '@looker/components-data'
import { Query, Sparkline, Table } from '@looker/visualizations'

// we assign this value to a constant to ensure that fields and data
// objects remain in sync.
const NESTED_DATA_KEY = 'orderCount'
const ROW_HEIGHT = 75

const nestSparklines = data => {
  return data.reduce((acc, d) => {
    // the first entry is the dimension (brand name), and the rest of the rows are the
    // quarterly sales information we want to pass to the Sparkline.
    const [parentDimension, ...measurePairs] = Object.entries(d)

    // `nonPivotedData` represents a single data row.
    // e.g. [{entry: 1, orderCount: 10}, {entry: 2, orderCount: 15}, ...etc]
    const nonPivotedData = measurePairs.map(([_, value], i) => {
      return { entry: i, [NESTED_DATA_KEY]: value }
    })

    // now for each row in the table we render a Sparkline using the `nonPivotedData`
    // that we built above.
    // E.G. [{products.brand: 'adidas', orderCount: <Sparkline />}]
    return [
      ...acc,
      {
        [parentDimension[0]]: parentDimension[1],
        [NESTED_DATA_KEY]: () => (
          <Sparkline
            height={ROW_HEIGHT}
            data={nonPivotedData}
            fields={{
              measures: [{ name: NESTED_DATA_KEY }],
              dimensions: [],
            }}
          />
        ),
      },
    ]
  }, [])
}

const CustomVis = ({ fields, data, pivots, config }) => {
  const nestedData = nestSparklines(data)

  return (
    <Table
      config={config}
      height={500}
      fields={{
        measures: [{ name: NESTED_DATA_KEY, label: 'Orders Count By Quarter' }],
        dimensions: fields.dimensions,
        pivots: [],
      }}
      data={nestedData}
      pivots={pivots}
      defaultRowHeight={ROW_HEIGHT}
    />
  )
}

export const MyReactApp = () => {
  const { core40SDK } = useContext(ExtensionContext)

  return (
    <DataProvider sdk={core40SDK}>
      <Query query='Uijcav7pCA4MZY2MompsPZ'>
        <CustomVis />
      </Query>
    </DataProvider>
  )
}

Étapes suivantes