ulysseswbdv
v1.1.74
Published
Ulysses Web(BDV)
Maintainers
Readme
Ulysses Web BDV Library
Install the Web BDV Ulysses library to quickly build Web BDVs with:
- shared header toolbar
- page navigation sidebar
- footer action bar
- iframe lifecycle helpers (close, save & close, etc.)
- built-in "Copy URL" deep link action (
copyurl)
📦 Installation
npm i ulysseswbdv⚙️ Configuration Objects
Your BDV defines three config arrays and passes them to the library.
export const toolbarActions = [
{
id: '',
name: '',
ico: '', // icon font class (e.g. "material-icons")
className: '', // css class for <a>
iconName: '', // icon name or text shown inside <span>
event: '', // e.g. 'closewindow', 'copyurl'
codeName: '', // internal key (e.g. 'save', 'menu', 'copyurl')
enabled: true,
visible: true
}
];
export const pages = [
{
id: '',
name: '',
url: '',
ComponentName: '', // e.g. 'PreviewForm'
active: false,
display: 'block' // or 'none' to hide in menu
}
];
export const footerActions = [
{
codeName: '',
id: '',
name: '',
page: '', // which page this action belongs to
iconName: '', // material icon name
enabled: true
}
];🧠 What the Library (<Index />) Does
ulysseswbdv/lib/Iframe:
Renders the standard BDV chrome (header / sidebar / footer).
Handles toolbar events like:
- close window
- close & refresh
- previous / next page
- copyurl
Copies the deep link to clipboard for you.
Shows success/error toast or fallback
alert.
You don't reimplement this logic in each BDV.
🔌 What Your BDV Must Do
Your BDV:
- Listen for
window.postMessagefrom TA Web. - Save that raw payload into state as
callerDataRaw(literallyevent.data). - Pass
callerDataRawinto<Index />. - Control which sub-page is currently displayed and which buttons are enabled.
You do not build the share URL yourself.
You do not expose getCopyUrl.
You do not manage clipboard logic.
All of that is handled inside the library based on callerDataRaw.
🛰 Getting callerDataRaw from postMessage
When TA Web opens your BDV in an <iframe>, it sends a message event that includes everything the BDV needs:
- token
- user info
- role / task / BU
- selected row(s)
- context selection
- etc.
You just store it.
class ManageInspectionInstance extends React.Component {
constructor(props) {
super(props);
this.state = {
callerDataRaw: null, // 👈 full event.data goes here
componentName: 'PreviewForm',
btnHeaderEnabled: [],
btnEnabled: [],
menuPages: true,
// ...other state...
};
}
componentDidMount() {
window.addEventListener('message', this.onIncomingMessage);
}
componentWillUnmount() {
window.removeEventListener('message', this.onIncomingMessage);
}
onIncomingMessage = (event) => {
// we only care about real TA Web data objects
if (typeof event.data !== 'object' || !event.data) return;
if ('type' in event.data) return; // ignore framework/system noise
// optional: store token for FetchData
if (event.data.Token) {
localStorage.setItem('authToken', event.data.Token);
}
// 🔴 IMPORTANT:
// We no longer reshape or normalize fields. We keep it RAW.
this.setState({
callerDataRaw: event.data
});
// ...anything else you already do on load (fetch inspection, etc)...
};
// ...
}That’s all.
callerDataRaw is literally event.data.
🔗 Deep Link / Copy URL (copyurl)
What the user does
User clicks the "Copy URL" (or similar) button in the BDV header toolbar.
What happens
Inside the library:
It reads
this.props.callerDataRaw.It builds a deep link back into the same BDV, using fields like:
parentURLFolderId,FolderRoleId,TaskIddirectoryIdSelectedRows[0].idIndex/ identifierscontextselection(joined if multiple)ActionId, etc.
It strips
/iframefromparentURLand appends the correct query string.It copies the final URL to the clipboard.
It shows success or error feedback (toast or alert).
You don’t write any of this logic.
🧩 Rendering <Index /> in Your BDV
import Index from 'ulysseswbdv/lib/Iframe';
import { toolbarActions } from './Utils/dataToolbar';
import { footerActions } from './Utils/actionsFooter';
import { pages } from './Utils/pagesInspection';
class ManageInspectionInstance extends React.Component {
// ...state, lifecycle, etc...
render() {
return (
<Index
toolbaractions={toolbarActions}
onSelectEvent={this.eventsHandler} // you still get custom toolbar events
pages={pages}
pageActions={footerActions}
onSelectPage={this.pagesHandler} // sidebar navigation click
onSelectPageActions={this.pagesActionsHandler} // footer button click
btnHeaderEnabled={this.state.btnHeaderEnabled} // runtime enable/disable for header actions
btnEnabled={this.state.btnEnabled} // runtime enable/disable for footer actions
pagesEnabled={this.state.menuPages} // show/hide left sidebar
callerDataRaw={this.state.callerDataRaw} // 👈 just pass event.data here
>
{this.state.componentName === 'PreviewForm' ? (
<PreviewForm
/* ...props... */
/>
) : this.state.componentName === 'FormInformation' ? (
<FormInformation
/* ...props... */
/>
) : null}
{/* example modals/popups managed by BDV */}
<Error
popupVisible={this.state.popupVisible}
OneventsHandlerCloseSave={this.eventsHandlerCloseSave}
OnhideInfo={this.hideInfo}
/>
<Queries /* ... */ />
<Warning /* ... */ />
</Index>
);
}
}Key points:
- You must pass
callerDataRawto<Index />. - You NO LONGER pass
getCopyUrl. - You NO LONGER set
generatedUrlyourself.
🔁 Toolbar Events in Your BDV
Your BDV may still keep logic like this:
eventsHandler = (item) => {
// The library now intercepts 'copyurl' internally,
// so you do NOT have to handle it here.
if (item.event === 'closewindow') {
PostCloseEvent();
return;
}
if (item.event === 'closewindowandrefresh') {
PostCloseAndRefreshEvent();
return;
}
if (item.event === 'forward') {
const idx = pages.findIndex(p => p.ComponentName === this.state.componentName);
if (pages[idx + 1]) {
this.setState({ componentName: pages[idx + 1].ComponentName });
}
return;
}
if (item.event === 'back') {
const idx = pages.findIndex(p => p.ComponentName === this.state.componentName);
if (pages[idx - 1]) {
this.setState({ componentName: pages[idx - 1].ComponentName });
}
return;
}
// custom BDV actions can go here...
};If the toolbar item is copyurl, you don’t need code.
<Index /> already handled it using callerDataRaw.
🖼 Host Page Requirements
Make sure the container page (the page where React mounts) includes the fonts/icons the library expects:
<head>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
</head>
<body class="skin-orange-light">
<div id="root"></div>
</body>✅ Summary
ulysseswbdvgives you a ready-made BDV shell (<Index />).Your BDV still controls:
- which internal page/component is showing,
- button enable/disable state,
- side menu visibility.
TA Web sends an initialization message to the iframe.
You store that message as-is:
this.state.callerDataRaw = event.data;You pass
callerDataRawinto<Index />.The library:
- understands that payload,
- builds the deep link,
- handles
copyurl, - copies to clipboard,
- shows feedback.
You stop doing:
- manual URL assembly,
- generatedUrl state,
- custom clipboard code
🗓️ Change Log
v1.1.74 — Unified Caller Data + Automatic Copy URL
Date: 2025-10-30 Highlights:
- The library now fully handles Copy URL (
copyurl) internally. - BDVs no longer need to pass
getCopyUrlor build their own URL. - The only requirement is to pass
callerDataRaw={event.data}to<Index />. buildShareUrland clipboard logic are automatically applied by the library.- Added internal feedback via
ToastServiceor fallbackalert(). - Simplified developer setup — fewer props, less boilerplate per BDV.
