Usar componentes de visualización para crear una visualización personalizada

Este tutorial está dirigido a desarrolladores de JavaScript con experiencia y presupone que tienen cierta familiaridad con las técnicas de programación funcional.

En este ejemplo, empezamos con una consulta relacionada con información hipotética sobre las ventas trimestrales de algunas marcas. Primero, filtraremos la consulta por marcas específicas y, después, dinamizaremos los resultados por trimestre de ventas. Consulta la siguiente tabla para ver un ejemplo.

Resultados de una consulta sobre el número de pedidos por marca, con un pivote en la dimensión Trimestre de creación de pedidos.

Después, usaremos componentes de visualización para crear una visualización personalizada que muestre cómo han evolucionado los productos de cada marca durante el último trimestre. El resultado será un nuevo tipo de visualización compuesto por una serie de gráficos de líneas anidados en una tabla, como en este ejemplo:

Una visualización personalizada que muestra una tabla con una fila por cada marca y una visualización de minigráfico de líneas insertada que muestra los pedidos por trimestre en cada fila.

Además de mostrarte cómo crear una visualización personalizada, en este ejemplo se ilustran algunas prácticas recomendadas para trabajar con la API de Looker en una aplicación React.

Para crear una visualización personalizada con componentes de Looker, asegúrate de que tu configuración cumple los requisitos y, a continuación, sigue estos pasos:

  1. Crear una consulta en Explorar y copiar el valor de qid
  2. Transferir los datos a un componente de visualización personalizada
  3. Crear el componente CustomVis
  4. Transformar los datos normalizados
  5. Insertar los datos transformados en CustomVis
  6. Generar la visualización personalizada

Usar componentes de visualización para crear una visualización personalizada es adecuado cuando la visualización personalizada está destinada a una aplicación o extensión insertada. Si quieres que la visualización personalizada esté disponible para los usuarios de Looker en una instancia de Looker, sigue las instrucciones que se indican en la página de documentación visualization. Si quieres desarrollar una visualización personalizada y subirla a Looker Marketplace, sigue las instrucciones de la página de documentación Desarrollar una visualización personalizada para Looker Marketplace.

Requisitos

Antes de empezar, necesitas algunos elementos:

  • Debes tener acceso a una instancia de Looker.
  • Tanto si desarrollas en el framework de extensiones como si lo haces en tu propia aplicación React independiente, es importante que te autentiques con la API de Looker y que tengas acceso al objeto del SDK de Looker. Consulta más información sobre la autenticación de la API de Looker o nuestro framework de extensiones.
  • Asegúrate de haber instalado el paquete NPM de componentes de visualización de Looker y el @looker/components-data paquete NPM. Puedes consultar información sobre cómo instalar y usar el paquete de componentes de visualización en el archivo README, disponible en GitHub y NPM.

Paso 1: Crea una consulta en un Exploración y copia el ID de la consulta

En este ejemplo, usamos información hipotética sobre las ventas trimestrales de las marcas a las que hacemos un seguimiento a lo largo del tiempo.

Vamos a dinamizar estos datos, ya que esta es la forma integrada de Looker de agrupar los resultados de las consultas. En un Exploración, podemos ejecutar una consulta y crear un gráfico de los datos con uno de los tipos de visualización nativos de Looker. El gráfico proporciona mucha información, pero es difícil analizar de un vistazo cómo evolucionan los productos de cada marca:

Gráfico resultante de una consulta de recuentos de pedidos por marca, con un pivote en la dimensión Trimestre de creación de pedidos.

El siguiente paso es copiar el valor de qid de la barra de URL de Explorar. En este ejemplo, el valor de qid será Uijcav7pCA4MZY2MompsPZ, pero ese valor es específico de nuestra instancia de prueba. El valor que obtengas será diferente.

Paso 2: Transfiere los datos a un componente de visualización personalizado

Para empezar, pasa el valor qid tomado de la URL de Explorar al componente Query y el objeto SDK autenticado a 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>
  )
}

A continuación, en lugar de renderizar una visualización nativa de Looker a través del componente Visualization, crearemos nuestro propio componente personalizado llamado CustomVis.

El componente Query puede aceptar cualquier elemento de React como elemento secundario y simplemente transferirá los valores config, data, fields y totals como propiedades para renderizar tus propios componentes de visualización. Renderizaremos CustomVis como elemento secundario de Query para que pueda recibir todos los datos relevantes como propiedades.

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>
  )
}

Paso 3: Desarrolla el componente CustomVis

A continuación, vamos a crear el componente CustomVis. Las propiedades que se heredan del componente Query son config, fields, data, pivots y totals:

  • config describe todas las formas en las que se deben representar los datos en un gráfico, como el grosor de la línea de un minigráfico o el tamaño y la forma de los puntos de un gráfico de dispersión.
  • fields almacena metadatos adicionales sobre los valores de las métricas y las dimensiones devueltos por la consulta, como el formato que deben tener los valores o la etiqueta que debe tener cada eje.
  • data es la respuesta de clave/valor que se ha devuelto de la consulta.
  • pivots describe la dimensión por la que se pivota la consulta.
  • totals hace referencia a los totales de filas de Looker para usarlos en visualizaciones basadas en tablas.

Podemos transferir estas propiedades sin modificar a una visualización de tabla insertando un componente 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} />
}

De esta forma, podemos hacernos una idea de los datos tal como los devuelve el SDK. En la respuesta renderizada, hay una fila por cada marca con los resultados agrupados o dinamizados por trimestre.

Paso 4: Transformar los datos normalizados

Para convertir estos datos dinamizados de forma que se representen con minigráficos anidados, aislamos todos los valores de medida y los enviamos a los subgráficos. En el siguiente gráfico, se resaltan los datos relevantes de una sola fila para ilustrar los datos que vamos a contraer y representar con una visualización secundaria:

Gráfico de resultados de datos con los recuentos de pedidos resaltados en la segunda fila.

Crearemos una transformación personalizada para ello. A continuación, se muestra un ejemplo específico de este caso. Deberá analizar sus propios datos en consecuencia.


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.
    // 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: [],
            }}
          />
        ),
      },
    ]
  }, [])
}

La función se crea siguiendo estos pasos:

  1. Reduce el conjunto de datos para aislar el nombre de la marca de los datos de pedidos trimestrales de cada fila.
  2. Actualiza cada fila para incluir la dimensión y un componente de React renderizado que pueda representar los valores de cada fila de la tabla.

Paso 5: Insertar los datos transformados en CustomVis

Ahora, transforma los datos con nuestra nueva función y asigna el resultado a una nueva variable llamada 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}
    />
  )
}

Paso 6: Generar la visualización personalizada

Una vez que haya insertado los datos transformados y configurado el gráfico, la visualización tendrá el siguiente aspecto (en este ejemplo, se trata de una tabla con gráficos de minilíneas individuales para cada fila):

Una visualización personalizada que muestra una tabla con una fila por cada marca y una visualización de minigráfico de líneas insertada que muestra los pedidos por trimestre en cada fila.

El código necesario para renderizar esta visualización es el siguiente:


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.
    // 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>
  )
}

Pasos siguientes