构建自定义扩展UI
NOTE
本文假定您对软件开发工具有一定的了解。
此过程描述如何生成用户实际看到的屏幕,以及如何使用Fusion完成连接(“握手”)。
在此过程中,请务必记住,扩展在两个框架中运行:隐藏的 注册 框架和可见的 UI 框架。
有关与自定义扩展相关的框架的信息,请参阅UI扩展中包含的框架。
有关构建注册框架的说明,请参阅创建用于UI扩展性的项目。
在两个帧之间布线
两帧加载相同的index.html;小型前端路由器根据URL决定要显示的组件。
-
在
web-src/src/components/App.js中设置路由。 关键部分是:code language-jsx import { HashRouter as Router, Routes, Route } from "react-router-dom"; import ExtensionRegistration from "./ExtensionRegistration"; import DashboardWidget from "./DashboardWidget"; export default function App() { return ( <Router> <Routes> {/* Background frame: registers the extension with Fusion */} <Route index element={<ExtensionRegistration />} /> <Route path="index.html" element={<ExtensionRegistration />} /> {/* Visible frame: the URL you returned from getWidget() */} <Route path="my-widget" element={<DashboardWidget />} /> </Routes> </Router> ); }这些路由将映射到以前的配置,如下所示:
- 默认路由(
index)呈现ExtensionRegistration,即调用register(...)的隐藏帧。 my-widget路由呈现您可见的UIDashboardWidget。 这与您在上一页中从getWidget()返回的url: "/index.html#/my-widget"匹配。
note NOTE 路由和 getWidgetURL必须一致。 如果更改路由名称,请同时更改url,否则Fusion将加载空白页。 - 默认路由(
-
继续完成与
attach的握手。
使用attach完成握手
这是可见UI中最重要的一行。 当Fusion打开您的UI框架时,将等待该框架“签入”。 您的代码通过调用attach({ id })签入。
如果省略,Fusion将超时,并出现错误,例如“正在等待来自目标iframe的初始消息。”
-
将以下内容添加到
web-src/src/components/DashboardWidget.js:code language-jsx import { useEffect, useState } from "react"; import { attach } from "@adobe/uix-guest"; import { extensionId } from "./Constants"; export default function DashboardWidget() { const [connection, setConnection] = useState(null); useEffect(() => { // Tell Fusion this UI frame is ready. Required. attach({ id: extensionId }) .then(setConnection) .catch((e) => console.error("attach failed", e)); }, []); if (!connection) { return <p>Connecting to Fusion...</p>; } return <h2>Hello from my Fusion extension!</h2>; }此代码执行以下操作:
- Fusion响应后,
attach({ id })将返回连接对象。 我们建议保存此内容,因为您将在下一步中使用它来读取Fusion发送的上下文。 - 在连接解析之前,出现一个简短的“Connecting…”(连接……) 将显示消息。
- 使用您在
Constants.js中设置的相同extensionId。
此时,您拥有一个有效的扩展:该扩展注册、附加和显示消息。 之后的所有工作都是关于使用数据融合的。
- Fusion响应后,
读取上下文Fusion共享
在附加该连接后,该连接会公开一个共享上下文,其中包含有关当前用户、组织和团队的信息。 您可以使用connection.sharedContext.get("<key>")读取单个值:
const orgId = connection.sharedContext.get("imsOrgId");
const organization = connection.sharedContext.get("organization"); // full Fusion org
const user = connection.sharedContext.get("user"); // full Fusion user
此示例显示了一个完整的被动示例,当用户切换组织或团队时,该示例也会更新:
import { useEffect, useState } from "react";
import { attach } from "@adobe/uix-guest";
import { extensionId } from "./Constants";
const KEYS = ["imsOrgId", "imsUserId", "organization", "team", "user"];
function readContext(source) {
// sharedContext behaves like a Map (.get); the change event gives a plain object.
const get =
typeof source.get === "function" ? (k) => source.get(k) : (k) => source[k];
return Object.fromEntries(KEYS.map((k) => [k, get(k)]));
}
export default function DashboardWidget() {
const [context, setContext] = useState(null);
useEffect(() => {
let cleanup = () => {};
attach({ id: extensionId })
.then((connection) => {
// 1) initial values
setContext(readContext(connection.sharedContext));
// 2) react to org/team/user changes pushed by Fusion
const onChange = (event) =>
setContext(readContext(event?.detail?.context ?? connection.sharedContext));
connection.addEventListener("contextchange", onChange);
cleanup = () => connection.removeEventListener?.("contextchange", onChange);
})
.catch((e) => console.error("attach failed", e));
return () => cleanup();
}, []);
if (!context) return <p>Connecting to Fusion...</p>;
return (
<div>
<h2>{context.organization?.name ?? "No organization"}</h2>
<p>Signed in as {context.user?.name} ({context.user?.email})</p>
<p>IMS org: {context.imsOrgId}</p>
</div>
);
}
请记住以下内容:
- 直接在
attach之后从connection.sharedContext.get(key)中读取初始值。 - 订阅
contextchange以保持同步。 每当活动的组织、团队或用户发生更改时,Fusion都会触发此事件。 新值在event.detail.context到达。
有关键的完整列表以及每个键所包含的内容,均包含在Fusion上下文引用中。
要继续配置自定义扩展的过程,请转到Fusion上下文引用。
recommendation-more-help
workfront-fusion-help-workfront-fusion