使用 Looker 组件构建标签页式信息中心

举一个简单的例子,说明界面组件如何增强嵌入式应用,就是使用它们为信息中心创建标签页式导航:

具有标签页式界面的示例信息中心。

以下示例将标签式信息中心添加到了使用 Looker 扩展程序框架构建的基本 TypeScript 扩展程序中。

如要完成此示例,请确保您的设置符合要求,然后按照以下步骤操作:

  1. 构建基本的 TypeScript 扩展程序
  2. 创建文件 src/Dashboards.tsx 以连接和存储信息中心。
  3. 创建 src/Tabs.tsx 文件以存储 Tabs 组件。
  4. 替换 src/App.tsx 中的 HelloWorld 引用。
  5. 使用嵌入使用权更新 manifest.lkml 文件。
  6. 将扩展程序发布到 Looker 实例。

使用要求

开始之前,您需要准备下列几项元素:

  • 您必须有权访问已启用扩展程序框架的 Looker 实例。
  • 您必须拥有 develop 权限。
  • 您应该在 Looker 中有多个用户定义的信息中心,以便将其放置在界面标签页中。
  • 无论您是在扩展程序框架中构建,还是在您自己的独立 React 应用中构建,都必须使用 Looker 的 API 进行身份验证并有权访问 Looker SDK 对象,这一点非常重要。如需了解详情,请参阅 Looker API 身份验证或我们的扩展框架
  • 此示例使用 Looker Embed SDK。若要允许 Embed SDK 针对您的实例运行,必须将 http://localhost:8080 添加到管理面板的嵌入页面内的嵌入式网域许可名单中。
  • 确保您已安装 Looker 组件 NPM 软件包。如需了解如何安装和使用组件软件包,请参阅 GitHubNPM 中的 README 文档。

第 1 步:构建基本的 TypeScript 扩展程序

请按照构建 Looker 扩展程序简介文档页面中的说明构建扩展程序。如需使该扩展程序成为 TypeScript 扩展程序,请使用以下修改:

  • 如果您使用 create-looker-extension 工具创建扩展程序模板,请在第二步中选择 TypeScript 作为您要使用的语言。
  • 如果您克隆 Git 代码库以创建扩展程序模板,请在第二步中导航到 extension-examples/react/TypeScript/helloworld-ts 目录。

第 2 步:创建文件 src/Dashboards.tsx 以连接并存储信息中心

在新扩展程序的 src 目录中,创建一个 Dashboards.tsx 文件。此文件将连接并存储您在 Looker 中构建的信息中心。

在该文件内,粘贴以下代码。此代码会创建三个信息中心对象,并按 ID 指定它们。您可以根据需要创建更多或更少的信息中心对象。

实例网址 https://mycompany.looker.com 的代码中有三个位置。请将其更改为您的 Looker 实例网址。

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%;
 }
`;

在上一个代码示例中,发生了以下情况:

  • import 语句引入所需的依赖项。

    import React, { useCallback } from "react";
    import { LookerEmbedSDK } from "@looker/embed-sdk";
    import styled from "styled-components";
    
  • 下一个代码块会创建一个 EmbeddedDashboard1 对象,该对象是包含信息中心 iframe 的 EmbedContainer 对象。iframe 是使用传递给它的信息中心 ID 从 Looker Embed SDK 生成的。请务必将 https://mycompany.looker.com/ 更新为 Looker 实例网址。

    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>;
    };
    
  • 接下来的两个代码块针对 EmbeddedDashboard2EmbeddedDashboard3 重复此过程。再次提醒一下,请务必将 https://mycompany.looker.com/ 更新为 Looker 实例网址。

  • 最后一个代码块用于设置 EmbedContainer 的样式。

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

第 3 步:创建文件 src/Tabs.tsx 以存储 Tabs 组件

在新扩展程序的 src 目录中,创建一个 Tabs.tsx 文件。此文件会存储 Tabs 组件,并引用每个信息中心的 Looker 信息中心 ID。

在该文件中,粘贴以下代码(下一节将介绍代码的用途):

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

在上一个代码示例中,发生了以下情况:

  • import 语句会引入所需的依赖项和组件,以及在 Dashboards.tsx 文件中创建的 EmbeddedDashboard 对象。

    import React from "react";
    import { ComponentsProvider, Tabs2, Tab2 } from "@looker/components";
    import { EmbeddedDashboard1, EmbeddedDashboard2, EmbeddedDashboard3,
    } from "./Dashboard";
    
  • 导出语句使 Tabs 对象可以导入到其他组件中。

    export const Tabs = () => (
    
  • ComponentsProvider 会封装各个组件,以帮助设置主题。

    <ComponentsProvider>
    </ComponentsProvider>
    
  • Tabs2 组件及其子组件 Tab2 创建了三个标签页,并将它们关联到 Looker 信息中心。

     <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>
    
    • Tab2id 属性接受唯一的标签页 ID。根据您的环境需要更新 ID。
    • label 属性接受将出现在每个标签页上的标签。根据您使用的信息中心更新 ID。
    • 放置在 Tab2 标记内的字符串会显示在该标签页的内容区域的顶部。根据需要更新或移除该字符串。
    • EmbeddedDashboard1EmbeddedDashboard1EmbeddedDashboard1 对象都放置在标签页中。其 id 属性可接受要嵌入到该标签页中的信息中心的信息中心 ID。在您构建自己的标签页式信息中心时,请将此值替换为您要使用的信息中心的信息中心 ID。您可以在网址中的 dashboards/ 后找到数字信息中心 ID。例如,如果网址为 https://example.looker.com/dashboards/61?Recording+Date=10+weeks&Country=US,则信息中心 ID 为 61

第 4 步:替换 src/App.tsx 中的 HelloWorld 引用

找到 src 目录中的 App.tsx 文件。移除 HelloWorld import 语句:

import { HelloWorld } from './HelloWorld'

并将其替换为:

import { Tabs } from './Tabs'

您也可以从此目录中删除 HelloWorld.tsx 文件,因为您不会再使用该文件。

第 5 步:使用嵌入使用权更新 manifest.lkml 文件

在 LookML 项目中,将以下使用权添加到 manifest.lkml 文件的“使用权”部分:

use_embeds: yes

manifest.lkml 文件应如下所示:

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

现在,您可以导航到您的扩展程序,它会显示在左侧导航面板的应用程序文件夹中。如果您已使用 yarn develop 启动本地开发服务器,则可以查看嵌入式标签页式信息中心。

第 6 步:将扩展程序发布到 Looker 实例

如需向其他 Looker 用户显示扩展程序,请按照以下步骤将扩展程序发布到 Looker 实例:

  1. 开发服务器运行后,转到 localhost:8080/bundle.js
  2. 将浏览器窗口的内容在本地计算机上以 .js 文件的形式保存。
  3. 确保您处于开发模式,然后将 .js 文件拖放到您的扩展程序项目中。保存更改。
  4. manifest.lkml 文件中,注释掉 url: "http://localhost:8080/bundle.js" 行。
  5. manifest.lkml 文件中,取消注释 # file: "bundle.js" 行,并确保文件名与您上传到项目的 .js 文件的文件名一致。保存更改。
  6. 提交和部署您的更改。

部署后,您无需再启动本地开发服务器即可查看该扩展程序。此外,如果您的 Looker 实例用户通过左侧导航面板的应用文件夹导航到该扩展程序,则应该能够看到该扩展程序。