Empezar a usar los componentes de visualización de Looker

Insertar contenido de Looker mediante iframes es solo uno de los métodos que pueden usar los desarrolladores cuando quieren añadir un panel de control, un Look o una Exploración a su aplicación web. En este tutorial se presenta otro método para los desarrolladores que quieran añadir una visualización de Looker a una aplicación React. Este tutorial se basa en un proyecto inicial de Create React App y usa componentes de visualización de Looker.

Estos son los pasos que se explican en este tutorial:

  1. Obtener el slug de la consulta de Looker
  2. Crear una aplicación React con componentes de visualización de Looker
  3. Crear un servicio auxiliar de backend
  4. Iniciar el servidor y la aplicación React

Obtener el slug de la consulta de Looker

Hay algunas cosas que se deben hacer en Looker, ya que la aplicación React depende de ellas.

Obtener un slug de consulta

Necesitas el ID o el slug de la consulta que se usará como propiedad del componente de visualización. En este artículo se explica cómo obtener el slug de una consulta a partir de una URL de Exploración.

Configurar CORS en una instancia de Looker

El uso compartido de recursos entre dominios (CORS) se controla mediante la misma lista de permitidos de dominios que la inserción.

Se explica con más detalle en la página de documentación sobre la inserción firmada.

  1. En tu instancia de Looker, ve a Administrar > Insertar plataforma. Para ello, se necesitan privilegios de administrador.
  2. La aplicación React se ejecuta de forma predeterminada en http://localhost:3000. Si añades esta dirección a la lista de permitidos de dominios insertados, le indicas a Looker que permita las solicitudes de la aplicación y que responda a esas solicitudes con la misma dirección. Este paso es obligatorio, ya que la aplicación hará solicitudes a la API de la instancia de Looker. De lo contrario, no habrá comunicación entre Looker y la aplicación.

Crear la aplicación React

El frontend de esta demo usa Create React App para crear la aplicación React de una sola página. Ejecuta los siguientes comandos en la carpeta raíz de la demo (get-started-viz-components) para crear la aplicación e instalar las dependencias:

npx create-react-app frontend-react cd frontend-react npm i
@looker/visualizations npm i @looker/components @looker/components-data
styled-components

Después de ejecutar estos comandos, la estructura de carpetas debería ser similar a esta:

Una carpeta llamada Frontend react, que contiene las carpetas Node modules, Public y src, así como los archivos call .gitignore, package-lock.json y package.json.

Consulta el archivo package.json y asegúrate de que react-dom también esté instalado. Si no lo está, instálalo ejecutando npm i react-dom.

El package.json de esta demo tiene este aspecto:

{
  "name": "frontend-react",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@looker/components": "^4.0.3",
    "@looker/components-data": "^1.0.0",
    "@looker/sdk": "^22.16.0",
    "@looker/sdk-rtl": "^21.4.0",
    "@looker/visualizations": "^1.1.1",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^12.1.0",
    "@testing-library/user-event": "^12.4.0",
    "i": "^0.3.7",
    "npm": "^8.19.2",
    "react": "^16.14.0",
    "react-dom": "^16.14.0",
    "react-scripts": "5.0.1",
    "styled-components": "^5.3.6",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Configurar las variables de entorno

Crea un archivo .env en el directorio raíz de la aplicación (./frontend-react) y define las siguientes variables:

REACT_APP_LOOKER_API_HOST=https://your-looker-instance.looker.com
REACT_APP_BACKEND_SERVER=http://localhost:3001/

REACT_APP_BACKEND_SERVER es la dirección del servicio auxiliar de backend que usaremos para hacer una llamada a la API de Looker y extraer el token de acceso.

REACT_APP_LOOKER_API_HOST es la dirección de la instancia de Looker que recibirá solicitudes de la API de la aplicación React.

Inicializar el SDK del lado del cliente

La aplicación React usará el SDK para hacer solicitudes de API al servidor de Looker. Como esto se hace en el frontend, puedes usar el siguiente elemento auxiliar para inicializar sdk:

import { Looker40SDK } from '@looker/sdk'
import {
  AuthToken,
  AuthSession,
  BrowserTransport,
  DefaultSettings,
} from '@looker/sdk-rtl'

class SDKSession extends AuthSession {
  // This is a placeholder for the fetchToken function.
  // It is modified to make it useful later.
  async fetchToken() {
    return fetch('')
  }

  activeToken = new AuthToken()
  constructor(settings, transport) {
    super(settings, transport || new BrowserTransport(settings))
  }

  // This function checks to see if the user is already authenticated
  isAuthenticated() {
    const token = this.activeToken
    if (!(token && token.access_token)) return false
    return token.isActive()
  }

  // This function gets the current token or fetches a new one if necessary
  async getToken() {
    if (!this.isAuthenticated()) {
      const token = await this.fetchToken()
      const res = await token.json()
      this.activeToken.setToken(res.user_token)
    }
    return this.activeToken
  }

  // This function authenticates a user, which involves getting a new token
  // It returns a modified object with a new authorization header.
  async authenticate(props) {
    const token = await this.getToken()
    if (token && token.access_token) {
      props.mode = 'cors'
      delete props.credentials
      props.headers = {
        ...props.headers,
        Authorization: `Bearer ${this.activeToken.access_token}`,
      }
    }
    return props
  }
}

// This class sets the fetchToken to use the 'real' address of the backend server.
class SDKSessionEmbed extends SDKSession {
  async fetchToken() {
    return fetch(`${process.env.REACT_APP_BACKEND_SERVER}`)
  }
}

// This creates a new session with the 'real' address of the backend server.
const session = new SDKSessionEmbed({
  ...DefaultSettings,
  base_url: process.env.REACT_APP_LOOKER_API_HOST,
})

// This exports the SDK with the authenticated session
export const sdk = new Looker40SDK(session)

Insertar la visualización en la aplicación

Ahora que tienes el slug de la consulta (en nuestro ejemplo, Jlm4YHPeT3lLGA9UtHjZcA) de la visualización y se ha creado una instancia del objeto sdk, el siguiente paso es usar los componentes de visualización de Looker para insertar y renderizar la visualización en la aplicación:

import { sdk } from '../src/helpers/CorsSession'
import { Query, Visualization } from '@looker/visualizations'
import { DataProvider } from '@looker/components-data'
import { ComponentsProvider } from '@looker/components'

function App() {
  return (
    <>
      <h1>Get started with Looker visualization components</h1>
      <ComponentsProvider>
        <DataProvider sdk={sdk}>
          {/* Change this query slug to match your query slug */}
          <Query query="Jlm4YHPeT3lLGA9UtHjZcA">
            <Visualization />
          </Query>
        </DataProvider>
      </ComponentsProvider>
    </>
  )
}

export default App

El frontend está listo. Puedes añadir más componentes, más estilos a la aplicación, etc.

Crear un servicio auxiliar de backend

El último paso es crear el servicio auxiliar de backend que recibirá la llamada del frontend, usará el SDK de Looker para Node para autenticar al usuario, extraerá su token de acceso y lo enviará de vuelta al frontend.

Para simplificar, vamos a crear un servidor de Node con un endpoint. El servidor usará las dependencias express, cors y @looker/sdk-node. Puedes ejecutar los siguientes comandos desde la carpeta raíz (get-started-viz-components):

mkdir backend-node
cd backend-node
npm init -y
npm i express cors @looker/sdk-node

Para autenticar el SDK desde el backend, usaremos un archivo looker.ini. Puede consultar más detalles sobre cómo rellenar el archivo en la página del SDK de Node. Después de ejecutar estos comandos, la estructura de carpetas debería ser similar a esta:

Una carpeta llamada backend-node, que contiene una carpeta llamada node_modules y los archivos looker.ini, package-lock.json, package.json y server.js.

El package.json debería tener este aspecto:

{
  "name": "looker-embed-backend",
  "version": "1.0.0",
  "description": "Backend helper service for getting started with Looker Viz components",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "author": "Looker",
  "license": "Apache-2.0",
  "dependencies": {
    "@looker/sdk-node": "^22.16.0",
    "cors": "^2.8.5",
    "express": "^4.18.2"
  }
}

A continuación, añadiremos este código a un nuevo archivo server.js:

const cors = require('cors')
const express = require('express')
const { LookerNodeSDK } = require('@looker/sdk-node')

const port = 3001
const app = express()
// The following init40 method will authenticate using
// the looker.ini file
const sdk = LookerNodeSDK.init40()

app.use(
  cors({
    origin: '*',
  })
)
app.use(express.json())

app.get('/', async (req, res) => {
  const userId = await sdk.ok(sdk.me('id'))
  const accessToken = await sdk.login_user(userId.id)
  const user = {
    user_token: accessToken.value,
    token_last_refreshed: Date.now(),
  }
  res.json({ ...user })
})

app.listen(port, async () => {
  console.log(`Backend Server listening on port ${port}`)
})

Iniciar el servidor y la aplicación React

  • Abre un terminal, ve a la carpeta backend-node y ejecuta npm start.
  • Abre una segunda terminal, ve a la carpeta frontend-react y ejecuta npm start.
  • Una vez que el servicio auxiliar de backend y la aplicación React estén en funcionamiento, puedes abrir el navegador e ir a http://localhost:3000/ para ver la visualización insertada en la aplicación.

Ver el código en GitHub