Fabric 工作负载开发工具包前端(预览版)

Microsoft Fabric 工作负载开发示例存储库用作将自定义 UX 工作负载与 Microsoft Fabric 集成的指南。 通过此项目,开发人员可以将自己的 UI 组件和行为无缝集成到 Fabric 的运行时环境中,从而实现快速试验和自定义。 开发人员可以使用 Fabric 开发工具包的框架来生成工作负载,并创建自定义功能来扩展 Fabric 体验。 Fabric 平台旨在与独立软件供应商 (ISV) 功能互操作。 例如,项编辑器允许通过在 Fabric 工作区项的上下文中嵌入 ISV 的前端,来创建本机一致的用户体验。

UX 工作负载前端是一个标准 Web 应用 (React),它合并了我们的工作负载客户端 SDK(标准 NPM 包)以启用其功能。 ISV 托管并在 Fabric 门户中沙盒 <iframe> 内运行它。 它提供了 ISV 特定的 UI 体验,例如项编辑器。 SDK 提供了将常规 Web 应用转换为在 Fabric 门户内无缝运行的微前端 Web 应用所需的所有必要接口、API 和启动函数。

SDK 提供了具有以下功能的示例 UI:

  • 展示大多数可用 SDK 调用的使用情况
  • 演示基于 Fluent UI 的可扩展功能区的示例,该功能区与 Fabric 的外观匹配
  • 允许轻松进行自定义
  • 使你可以在 Fabric 开发模式下实时观测 Fabric 中的更改

先决条件

  • UX 工作负载 Web 应用

    此包基于 Fluent UI 生成,专为 React 设计。

  • UX 工作负载前端清单

    UX 工作负载前端清单是 ISV 提供的 JSON 资源。 它包含有关工作负载的基本信息(例如工作负载 Web 应用的 URL),以及各种 UI 详细信息(例如 ISV 项的显示名称和关联的图标)。 它还使 ISV 能够自定义用户在 Fabric 门户中与其项交互时发生的情况。

在此包中,清单文件位于此处,即包文件夹:“前端清单文件”下,可以在前端清单文件中找到详细描述。

步骤 1:在 Fabric 中启用工作负载开发功能

租户管理员必须在管理门户中启用工作负载开发功能。 可以通过启用租户开关“容量管理员可以开发其他工作负载”,为整个组织或组织内的特定组启用它。

工作负载开发租户开关的屏幕截图。

步骤 2:设置前端

要设置示例项目的前端,请遵照以下步骤操作:

  1. 验证是否已安装 Node.jsnpm,且 npm 版本至少为 9(否则,请安装最新的 Node.jsnpm

  2. 克隆存储库:克隆此处找到的存储库:https://go.microsoft.com/fwlink/?linkid=2272254

    这是包目录布局,其中包含基本组件和资源的描述:

    • - 工作负载包的位置:前端资源,包括清单和资产。
    • src - 工作负载代码:
      • index.ts - 主初始化文件,bootstrap index.workerindex.ui iFrame - 下面详细介绍
      • App.tsx - 将路径路由到页面,例如,在 components 下,/sample-workload-editor 路由到 SampleWorkloadEditor 函数
      • 资产 - 图像(jpgjpegpng)的位置,可以在清单中引用,并在 UI 中显示。 例如,在清单中 assets/github.jpg 设置为产品的图标。
      • 组件 - 实际 UI 代码的位置 - 编辑器视图,以及示例使用的其他视图(功能区、身份验证页、面板等)
      • 控制器 - 调用 SDK API 的控制器
      • 模型 - UI 本身使用的以及用于与样板后端通信的协定和模型
    • 工具 -
      • webpack.config.js - 本地 Node.js 服务器的配置
      • Web 配置和清单读取器/处理器
    • validation -
      • validateSchema.js - 验证产品和项目 json 文件架构。 它配置为在 npm start 上运行。
  3. 安装

    在存储库文件夹下,转到 Frontend 并运行 npm install

    <repository folder>\Frontend> npm install
    
  4. 启动服务器

    <repository folder>\Frontend> npm start
    

    此命令会启动 Microsoft Fabric 在开发模式下连接到的本地 Node.js 服务器(使用 webpack)。

    有关启动后出现的端口详细信息,请参阅 localhost 服务器说明。 当前的端口是 60006。 localhost 服务器启动后,打开 URL:127.0.0.1:60006/manifests 会获取从“Frontend/Package”文件夹创建的聚合清单。 打开以验证服务器是否已启动且正在运行。

    如果已连接,修改源文件会触发通过 webpack 重新加载 Fabric 中的内容。 但是,通常仍需刷新页面。

    如果更改“Frontend/Package”文件夹下的文件,则应再次执行“npm start”。

  5. 在 Fabric 中运行,启用 Fabric 开发人员模式设置,以允许 Fabric 访问 localhost 服务器。 转到开发人员设置 -->Fabric 开发人员模式并刷新页面。 此设置会保留在当前浏览器中。

    开发人员模式下的产品切换器示例的屏幕截图。

用法示例

要运行典型 Hello World 测试方案,请执行以下操作:

  1. 启动本地服务器并启用开发模式。 左下角的菜单应显示新的示例工作负载:

    产品切换器示例图的屏幕截图。

  2. 选择“示例工作负载”,并将用户导航到示例工作负载主页。 上半部分显示“创建体验”:

    示例扩展主页上的“创建卡片”图像的屏幕截图。

  3. 选择示例工作负载卡,以在 Fabric 内打开示例工作负载的 UI:

    主示例 UI 图像界面的屏幕截图。

浏览各种控件以查看 Fabric 的 WorkloadClient API (SDK) 功能:

  • 打开通知和对话框
  • 导航到页面
  • 获取主题和工作负载设置
  • 执行操作

大多数可用的 SDK 功能要么连接到按钮的操作,要么注册为回调。 结果通常是通知或消息框,显示已调用 API。

例如:

  • “执行操作”使用名为 sample.Action 的操作调用 action.execute() API。 此操作的功能是显示通知。
  • 在功能区上选择“保存”以调用 dialog.open() API,这将打开一个对话框,其中用户提供一个名称并在 Fabric 中保存项(此对话框将在 CRUD 部分中进一步探讨)。
  • “获取主题设置”按钮显示 Fabric 的主题配置列表(通过 theme.get() API)。

示例工作负载 UI 托管在 Fabric 沙盒 iframe 中,在检查页面的 DOM 时可以看到:

iFrame 嵌入图像的屏幕截图。

注意

沙盒 iframe 允许以下属性:allow-same-origin、allow-scripts。 有关沙盒和不同属性的含义的详细信息,请参阅 MDN Web 文档

步骤 3:深入了解代码

bootstrap()

在启动之前,检查路径以了解是否需要关闭窗口。 身份验证 API 需要此步骤。

const redirectUriPath = '/close';
const url = new URL(window.location.href);
if (url.pathname?.startsWith(redirectUriPath)) {
    window.close();
}

每个 Fabric 工作负载应用都需要支持以两种模式加载:

  • UI 模式:UI 模式下的应用在可见的 iFrame 中加载,并侦听自己的路由更改以呈现相应的 UI 组件,包括页面、面板、对话框等。
  • 辅助角色模式:辅助角色模式中的应用在一个不可见的 iFrame 中运行,它主要用于接收从外部世界发送的命令并对其进行响应。 @ms-fabric/workload-client 提供了 bootstrap() 方法来简化初始化步骤。 bootstrap() 方法在内部检测当前应用是在 UI 模式还是在辅助角色模式下加载,然后调用相应的初始化方法(initializeUI 或 initializeWorker)。 初始化完成后,bootstrap() 会通知 Fabric 微前端框架初始化成功或失败。
bootstrap({
    initializeWorker: (params) =>
        import('./index.worker').then(({ initialize }) => initialize(params)),
    initializeUI: (params) =>
        import('./index.ui').then(({ initialize }) => initialize(params)),
});

index.worker

这是主 onAction 注册。 它处理从 Fabric 主机发送的事件,这些事件本身由执行的操作触发。 这些操作可由工作负载本身发送到 Fabric,然后调用回 onAction 处理程序,或者也可以由 Fabric 主机启动。 例如,在单击“仅创建示例项 – 前端”时),Fabric 会触发操作 'open.createSampleWorkloadFrontendOnly',且 onAction 处理程序会启动打开工作负载主 UI 页面,如以下代码所示。 当前工作区 objectId 也会传入仅限前端的体验。

   workloadClient.action.onAction((message) => {
        switch (message.action) {
            /**
             * This opens the Frontend-only experience, allowing to experiment with the UI without the need for CRUD operations.
             * This experience still allows saving the item, if the Backend is connected and registered
             */
            case 'open.createSampleWorkloadFrontendOnly':
                const { workspaceObjectId: workspaceObjectId1 } = data as ItemCreateContext;
                return workloadClient.page.open({
                    extensionName: 'Org.WorkloadSample',
                    route: {
                        path: `/sample-workload-frontend-only/${workspaceObjectId1}`,
                    },
                });

                // ... elided for brevity...
            default:
                throw new Error('Unknown action received');
        }
    });

index.ui

initialize() 函数呈现嵌入 App 函数的 React DOM。 要进行 API 调用,传递 workloadClient SDK 句柄,此句柄在整个代码中使用。 FluentProvider 类确保在各种 FluentUI 控件之间保持样式一致性。

ReactDOM.render(
       <FluentProvider theme={fabricLightTheme}>
           <App
               history={history}
               workloadClient={workloadClient}
           />
       </FluentProvider>,
       document.querySelector("#root")
   );

开发流

  • App 将代码路由到会返回 SampleWorkloadEditor函数 React.JSX.Element 中。
  • 此函数包含 UI 结构(功能区和页面上的控件 - 按钮、输入字段等)。
  • 从用户收集的信息通过 React 的 useState() 挂钩存储。
  • UI 控件的处理程序会调用 SampleWorkloadController 函数,并传递相关的状态变量。
  • 为了支持 CRUD 操作,创建/加载项的状态将存储在 artifactItem 中,以及 workspaceObjectId 和有效负载变量的示例实现。

具有 notification.open() API 的示例:

  • state:

        const [apiNotificationTitle, setNotificationTitle] = useState<string>('');
        const [apiNotificationMessage, setNotificationMessage] = useState<string>('');
    
  • UI:

    • 标题:

      <Field label="Title" validationMessage={notificationValidationMessage} orientation="horizontal" className="field">
           <Input size="small" placeholder="Notification Title" onChange={e => setNotificationTitle(e.target.value)} />
         </Field>
      
    • “发送”按钮:

        <Button icon={<AlertOn24Regular />} appearance="primary" onClick={() => onCallNotification()} > Send Notification </Button>
      
    • 处理程序:

        function onCallNotification() {
         ... elided for brevity
          callNotificationOpen(apiNotificationTitle, apiNotificationMessage, undefined, undefined, workloadClient, setNotificationId);
        };
      
  • 控制器:

      export async function callNotificationOpen(
        title: string,
        message: string,
        type: NotificationType = NotificationType.Success,
        duration: NotificationToastDuration = NotificationToastDuration.Medium,
        workloadClient: WorkloadClientAPI,
        setNotificationId?: Dispatch<SetStateAction<string>>) {
    
        const result = await workloadClient.notification.open({
            notificationType: type,
            title,
            duration,
            message
        });
        if (type == NotificationType.Success && setNotificationId) {
            setNotificationId(result?.notificationId);
        }
    }
    

CRUD 操作

虽然仅限前端的开发方案很容易得到支持,但完整的端到端开发人员体验需要保存、读取和编辑现有的工作负载项。 后端实现指南详细介绍了如何设置和使用后端。

一旦后端启动并正在运行,且 Org.WorkloadSample.SampleWorkloadItem 类型在 Fabric 中注册,你就可以对此类型执行 CRUD 操作。 以下操作通过 ItemCrud API 公开。

CREATE

首次保存工作负载项时实现的对 create 的示例调用:

 const params: CreateItemParams = {
        workspaceObjectId,
        payload: { artifactType, displayName, description, workloadPayload: JSON.stringify(workloadPayload), payloadContentType: "InlineJson", }
    };
 const result: CreateItemResult = await workloadClient.ItemCrud.createItem(params);

我们的示例实现将创建的项存储在 artifactItem 内。 该项在当前选定的工作区下创建。 因此,工作区必须分配给后端配置所配置的容量,如后端文档中详述。尝试在不兼容的工作区下创建项失败。

  • 后端中的 onCreateFabricItem 回调阻止 CREATE 调用 - 如果失败,则会导致操作失败,并且 Fabric 中未创建任何项。 请参阅后端的调试/TSG 文档。

  • 目前,已保存项不会自动显示在工作区中。 需要页面刷新。

GET

在工作区视图中选择现有示例工作负载项时,Fabric 会导航到在 artifacts-->editor-->path 下前端清单中定义的路由:

"artifacts": [
  {
   "name": "Org.WorkloadSample.SampleWorkloadItem",
   "editor": {
    "extension": "Org.WorkloadSample",
    "path": "/sample-workload-editor"
   },

调用 itemCrud.getItem 时,数据将从 Fabric 的后端(与工作负载后端中的数据一起)加载,并加载到打开的 GUI 的 artifactItem 对象中。

在工作区中打开现有项的屏幕截图。

UPDATE

使用 itemCrud.updateItem 更新现有项。 工作负载有效负载本身由工作负载后端更新,而在 Fabric 中,只有项的 lastModifiedTime 已更改。

DELETE

从 Fabric 的工作区视图中调用(作为可用于所有项的常规操作)或通过工作区对 itemCrud.deleteItem 的显式调用来调用删除操作。 这两个调用都会经历工作负载后端的 onDeleteItem 回调。

身份验证

在示例工作负载编辑器中,有一个部分可让你导航到身份验证部分。 在使用身份验证 API 之前,配置 Microsoft Entra 应用 Microsoft Entra ID。 此外,请确保正确配置 env.dev 文件。 有关更多详细信息,请参阅:配置工作负载本地清单并获取应用程序的令牌

步骤 4:调试

要查看辅助角色和 UI iFrame,打开浏览器的 DevTools 的“源”选项卡 (F12)。

VS Code 中的调试文件的屏幕截图。

可以在辅助角色 iFrame 中放置断点,并查看传入操作上的主 switch。 还可以调试 UI iFrame,例如 SampleWorkloadEditor 内的代码。

Fluent UI 控件

UX 工作负载使用 Fluent UI 控件确保与 Fabric 的视觉一致性,并且易于开发。 示例工作负载提供了关于如何使用最常见控件的示例。 可在 Fluent UI 页上找到更多信息。

前端清单自定义

前端清单描述了工作负载的前端方面 - 产品外观、名称、视觉资产、可用操作等等。 它是 Fabric 与工作负载之间的主要联系点。 对于我们的示例工作负载, 清单在开发人员模式下加载到 Fabric 中,其各个部分、定义和清单示例显示在前端清单文件中。 在页面刷新后,实时查看对清单项的更改、不同操作的连接和视觉资产的更新。

客户端 SDK - 支持的 API

客户端 SDK 文档位于此处:@ms-fabric/workload-client 包

支持以下 API:

  • notification.open
  • notification.hide
  • panel.open
  • panel.close
  • action.onAction
  • action.execute
  • navigation.navigate
  • navigation.onNavigate
  • navigation.onBeforeNavigateAway
  • navigation.onAfterNavigateAway
  • page.open
  • dialog.openDialog
  • dialog.openMessageBox
  • dialog.close
  • theme.get
  • theme.onChange
  • settings.get
  • settings.onChange
  • errorHandling.openErrorDialog
  • errorHandling.handleRequestFailure
  • itemCrud.createItem
  • itemCrud.getItem
  • itemCrud.updateItem
  • itemCrud.deleteItem
  • itemSchedule.runItemJob
  • itemSchedule.cancelItemJob
  • itemRecentRuns.open