Lookerで実現!タブ付きダッシュボードの作成テクニック!!

Google Cloud
この記事は約14分で読めます。

こんにちは!石黒です。
みなさんはLookerのダッシュボードにタブを実装して、可読性を向上させたり、データ分析を加速したいと思ったことはないでしょうか?

Lookerではデフォルトで備わっていない機能であっても、拡張機能を実装することで実現できることがあります。タブ付きダッシュボードもその1つです。
ということで本記事ではLookerのダッシュボードにタブを実装する方法をご紹介します。

本記事でわかること

  • Lookerの拡張機能とは
  • タブ付きダッシュボードの実装手順
  • Windowsで実装する場合の注意点

Lookerの拡張機能とは

Lookerの拡張機能とは、Lookerの基本的なデータ探索やダッシュボード機能に対して、UIや機能を追加するためのカスタムアプリケーションです。
これにより、Lookerの標準機能を超えて、特定のビジネスニーズやユースケースに合わせた柔軟なデータ分析体験を提供できます。​

Looker拡張機能は、Node.jsやReactをベースにして開発されることが多く、Lookerが提供するCLIツール(yarn create looker-extension など)を使用してプロジェクトのセットアップを行います。​また、Looker APIやSDKを活用し、LookMLのデータモデルとやり取りすることで機能を構築します。

事前準備

実装を始める前にいくつか事前に準備が必要です。

Lookerでの事前準備

  • LookMLプロジェクトやデータベース接続が済んでいること
  • タブに分けたいダッシュボードが事前に用意されていること
  • 作業者にdevelop権限が割り当てられていること
  • 拡張フレームワークが有効になっていること

拡張フレームワークが有効になっているかどうかは、Lookerメイン画面より「管理者」→「プラットフォーム」→「拡張フレームワーク」から確認できます。
デフォルトでは有効になっていますが、念の為確認してから実装することを推奨します。

ローカル端末での準備

  • Node.jsがインストールされていること
  • Visual Studio Codeがインストールされていること​

それぞれ実装で使用するため、予め公式サイトからインストールをお願いします。

Node.jsがインストールできたら下記コマンドを実行してください。

・yarnのインストール

npm install -g yarn

・フォルダ削除パッケージのインストール(Windowsの場合のみ)

npm install -g rimraf

これで準備は完了です!

実装手順

手順1.TypeScript 拡張機能を作成する

まずはLookerの拡張機能をビルドしていきましょう。
Lookerでは、以下の2種類の方法で拡張機能のテンプレートコードファイルを生成できます。

本記事では前者の方法を選択します。

コマンドプロンプトで以下のコマンドを実行してください。
<extension_name>には任意の名称を置き換えてください。

yarn create looker-extension < extension_name >

実行すると3回選択が問われます。それぞれ以下のとおり選択して都度Enterキーを押してください。
1.What would you like to call this extension? :そのままEnter
2.What language would you like to use? :Typescriptを選択します
3.What framework would you like to use? :Reactを選択します

完了後、作成されたディレクトリへ移動し、依存関係をインストールします。

cd < extension_name >
yarn install

手順2.Dashboards.tsx ファイルを作成

ここからはVisual Studio Codeで作業を行います。
先ほどのディレクトリのままでコマンドを実行します。

code .

すると作成された拡張機能のディレクトリが表示されます。


まずはsrcディレクトリに「Dashboards.tsx」ファイルを作成します。

ファイル内に次のコードを貼り付けます。

import React, { useCallback } from "react";
import { LookerEmbedSDK } from "@looker/embed-sdk";
import styled from "styled-components";

export const EmbeddedDashboard1 = (props: { id: number | string }) => {
 const [dashboard, setDashboard] = React.useState();
 const setupDashboard = (dashboard: any) => {
   setDashboard(dashboard);
 };
 const embedCtrRef = useCallback((el) => {
   const hostUrl = "https://mycompany.looker.com/";
   if (el && hostUrl) {
     el.innerHTML = "";
     LookerEmbedSDK.init(hostUrl);
     LookerEmbedSDK.createDashboardWithId(props.id)
       .withNext()
       .appendTo(el)
       .build()
       .connect()
       .then(setupDashboard)
       .catch((error) => {
         console.error("Connection error", error);
       });
   }
 }, []);
 return <EmbedContainer ref={embedCtrRef}></EmbedContainer>;
};

export const EmbeddedDashboard2 = (props: { id: number }) => {
 const [dashboard, setDashboard] = React.useState();
 const setupDashboard = (dashboard: any) => {
   setDashboard(dashboard);
 };
 const embedCtrRef = useCallback((el) => {
   const hostUrl = "https://mycompany.looker.com/";
   if (el && hostUrl) {
     el.innerHTML = "";
     LookerEmbedSDK.init(hostUrl);
     LookerEmbedSDK.createDashboardWithId(props.id)
       .withNext()
       .appendTo(el)
       .build()
       .connect()
       .then(setupDashboard)
       .catch((error) => {
         console.error("Connection error", error);
       });
   }
 }, []);
 return <EmbedContainer ref={embedCtrRef}></EmbedContainer>;
};

export const EmbeddedDashboard3 = (props: { id: number }) => {
 const [dashboard, setDashboard] = React.useState();
 const setupDashboard = (dashboard: any) => {
   setDashboard(dashboard);
 };
 const embedCtrRef = useCallback((el) => {
   const hostUrl = "https://mycompany.looker.com/";
   if (el && hostUrl) {
     el.innerHTML = "";
     LookerEmbedSDK.init(hostUrl);
     LookerEmbedSDK.createDashboardWithId(props.id)
       .withNext()
       .appendTo(el)
       .build()
       .connect()
       .then(setupDashboard)
       .catch((error) => {
         console.error("Connection error", error);
       });
   }
 }, []);

 return <EmbedContainer ref={embedCtrRef}></EmbedContainer>;
};

export const EmbedContainer = styled.div`
 width: 100%;
 height: 95vh;
 & > iframe {
   width: 100%;
   height: 100%;
 }
`;

次に、貼り付けたソースを修正していきます。

コピーしたソースにはインスタンスURLが3か所に記載されており、該当箇所をそれぞれ実際のインスタンスURLに置き換える必要があります。

変更前:https://mycompany.looker.com​
変更後:実際のLooker環境から取得したURL

実際のインスタンスURLはLookerのメイン画面から「管理者」→「全般」→「設定」を選択したページにあるホストURLから確認することができます。

手順3.Tabs.tsxファイルを作成

もう一つファイルを追加します。
同じくsrcディレクトリ配下に「Tabs.tsx」というファイルを作成します。

ファイル内に次のコードを貼り付けます。

import React from "react";
import { ComponentsProvider, Tabs2, Tab2 } from "@looker/components";
import { EmbeddedDashboard1, EmbeddedDashboard2, EmbeddedDashboard3,
} from "./Dashboards";

export const Tabs = () => (
 <ComponentsProvider>
   <Tabs2>
     <Tab2 id="5" label="Order Analysis Dashboard">
      Order data from the last 12 months
       <EmbeddedDashboard1 id={5} />
     </Tab2>
     <Tab2 id="2" label="Inventory Dashboard">
       Current global inventory
       <EmbeddedDashboard2 id={2} />
     </Tab2>
     <Tab2 id="7" label="Customer Dashboard">
       Anonymized customer data
       <EmbeddedDashboard3 id={7} />
     </Tab2>
   </Tabs2>
 </ComponentsProvider>
)

貼り付けたソースを修正します。
タブのファイルでは予め用意したダッシュボードのIDを記載します。

ダッシュボードIDは、ダッシュボードURLのdashboards/ の後を確認します。​
例) https://example.looker.com/dashboards/61?Recording+Date=10+weeks&Country=US の場合、ダッシュボード ID は 61 です。

idプロパティを実際のIDに置き換えます。

手順4.App.tsxの修正

srcディレクトリ配下にある「App.tsx」ファイルを以下のとおり2か所修正します。

変更前:import { HelloWorld } from ‘./HelloWorld’​
変更後:import { Tabs } from ‘./Tabs’​

変更前:<HelloWorld/>​
変更後:<Tabs/>

修正後の実際の画面はこちらです。

手順5.ソースをビルドし、Lookerに追加する

Windows端末をお使いの場合は、ビルドを行う前に「package.json」の内容を3か所終了します。

変更前:​
“analyze”: “export ANALYZE_MODE=static && npm run build”,​
“build”: “export BABEL_ENV=build && webpack –config webpack.prod.js“,​
“clean”: “rm -rf dist && rm -f .eslintcache”,​

変更後:​
“analyze”: “set ANALYZE_MODE=static && npm run build”,​
“build”: “set BABEL_ENV=build && webpack –config webpack.prod.js“,​
“clean”: “rimraf -rf dist && rm -f .eslintcache”,

修正後にビルドを行います。

yarn build

ビルドを行うと、distフォルダが新たに作成され、中に「bundle.js」が用意されています。
このファイルをLookMLプロジェクトに追加します。追加はドラッグアンドドロップで可能です。

手順6.manifest.lkml ファイルをLookerプロジェクトに追加する

LookMLプロジェクトにマニフェストファイルを追加します。

プロジェクトのプラスボタンから「プロジェクトマニフェストを作成」を選択します。

マニフェストファイルを用意した後は、ファイルにコードを記入します。
拡張機能のフォルダ直下に「manifest.lkml」というファイルが予め用意されているので、このソースをまずはそのままLookMLプロジェクトのマニフェストファイルへコピーしてください。

ソースをコピーした後、entitlements セクションに、次のコードを追加します。

use_embeds: yes

また、url: “http://localhost:8080/bundle.js” の行をコメントし、​# file: “bundle.js” の行のコメントを解除します。

修正後のマニフェストファイルは以下のとおりです。

application: < extension_name > {
  label: "< extension_name >"
  # url: "https://localhost:8080/bundle.js"
  file: "bundle.js"
  entitlements: {
    core_api_methods: ["me"] #Add more entitlements here as you develop new functionality
    use_embeds: yes
  }
}

以上で実装は完了です!

手順7.実際に確認する

タブ付きダッシュボードが作成されているか確認してみましょう。

Lookerのメイン画面から「アプリケーション」を選択します。ドロップダウンリストを開き、マニフェストファイルで指定した名称が選択できるようになっていれば成功です。

アプリケーション名を選択すると、タブ付きダッシュボードへと遷移しました!

まとめ

いかがでしたでしょうか。
今回はLookerに拡張機能を実装し、ダッシュボードにタブ機能を追加する方法をご紹介しました。タブ以外にもLookerには様々な拡張機能が用意されているため、自身のビジネスニーズによって柔軟にカスタマイズが可能です。
皆さんも是非Lookerの拡張機能を実際の業務で使ってみてください!

Google および Google Cloud Platform™ service は Google LLC の商標であり、この記事は Google によって承認されたり、Google と提携したりするものではありません。

コメント

タイトルとURLをコピーしました