Introdução aos componentes de visualização do Looker

A incorporação de conteúdo do Looker pelo iframe é apenas um dos métodos que os desenvolvedores podem usar para adicionar um dashboard, um Look ou um Explore ao aplicativo da Web. Este tutorial apresenta outro método para desenvolvedores que querem adicionar uma visualização do Looker em um app React. Ele é baseado em uma ativação simples do app React para criar e usa componentes de visualização do Looker.

Estas são as etapas deste tutorial:

  1. Acessar o slug de consulta do Looker
  2. Criar um aplicativo React com componentes de visualização do Looker
  3. Criar um serviço auxiliar de back-end

Acessar o slug de consulta do Looker

Há algumas coisas que precisam ser feitas no Looker, porque o app React depende delas.

Acessar um slug de consulta

Você precisa do ID ou slug da consulta que será usado como uma propriedade do componente de visualização. Este artigo explica como você pode encontrar o slug de consulta de um URL de exploração. Confira outro exemplo na documentação do Looker.

Configurar o CORS na instância do Looker

O compartilhamento de recursos entre origens (CORS, na sigla em inglês) é controlado pela mesma lista de permissões de domínio que a incorporação.

Isso é documentado com mais detalhes na página de documentação Incorporação assinada.

  1. Navegue até Administrador > Incorporação da plataforma na sua instância do Looker. Isso exige privilégios de administrador.
  2. O app React é executado por padrão em http://localhost:3000. Ao adicionar esse endereço à lista de permissões de domínios incorporados, você informa ao Looker para permitir solicitações do app e responder a elas pelo mesmo endereço. Essa etapa é obrigatória, já que o app fará solicitações de API para a instância do Looker. Caso contrário, não vai haver comunicação entre o Looker e o app.

Criar o aplicativo React

O front-end dessa demonstração usa Criar app React para criar o aplicativo React de página única. Execute os comandos abaixo na pasta raiz da demonstração (get-started-viz-components) para criar o app e instalar as dependências:

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

Depois de executar os comandos, a estrutura de pastas vai ficar assim:

Uma pasta chamada Front-end reagir, contendo as pastas módulos Node, Public e src, e os arquivos chamam .gitignore, package-lock.json e package.json.

Verifique o arquivo package.json e confira se react-dom também está instalado. Caso contrário, instale-o executando npm i react-dom.

O package.json dessa demonstração fica assim:

{
  "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 as variáveis de ambiente

Crie um arquivo .env no diretório raiz do app (./frontend-react) e defina as seguintes variáveis:

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

REACT_APP_BACKEND_SERVER é o endereço do serviço auxiliar de back-end que vamos usar para fazer uma chamada de API ao Looker e extrair o token de acesso.

REACT_APP_LOOKER_API_HOST é o endereço da instância do Looker que receberá solicitações de API do app React.

Inicializar o SDK do lado do cliente

O app React vai usar o SDK para fazer solicitações de API ao servidor do Looker. Como isso é feito no front-end, use o auxiliar a seguir para inicializar o 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 used above
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)

Incorporar a visualização no app

Agora que você tem o slug de consulta (no nosso exemplo é Jlm4YHPeT3lLGA9UtHjZcA) da visualização e o objeto sdk foi instanciado, a próxima etapa é usar os componentes da visualização do Looker para incorporar e renderizar a visualização no app:

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

O front-end está pronto. Você pode adicionar mais componentes, incluir mais estilo no app etc.

Criar um serviço auxiliar de back-end

A etapa final é criar o serviço auxiliar de back-end que receberá a chamada do front-end, usar o SDK do Looker-Node para autenticar o usuário, extrair o token de acesso dele e enviá-lo de volta ao front-end.

Para simplificar, vamos criar um servidor de nó com um endpoint. O servidor usará as dependências express, cors e @looker/sdk-node. É possível executar os seguintes comandos começando na pasta raiz (get-started-viz-components):

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

Para autenticar o SDK pelo back-end, usaremos um arquivo looker.ini. Você pode encontrar mais detalhes sobre como preencher o arquivo na página SDK-Node. Depois de executar os comandos, a estrutura de pastas vai ficar assim:

Uma pasta chamada "backend-node", contendo uma pasta chamada node_modules e os arquivos looker.ini, package-lock.json, package.json e server.js.

O package.json vai ficar assim:

{
  "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"
  }
}

Em seguida, vamos adicionar esse código a um novo arquivo server.js:

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

const port = 3001
const app = express()
// The init40 method below 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 o servidor e o app React

  • Abra um terminal, navegue até a pasta backend-node e execute npm start
  • Abra um segundo terminal, navegue até a pasta frontend-react e execute npm start
  • Quando o serviço auxiliar de back-end e o app de reação estiverem em execução, abra o navegador e acesse http://localhost:3000/ para exibir a visualização incorporada ao aplicativo.

Confira o código no GitHub