Files
inter-hub/docs/annotation-launcher.md
Bernd Worsch 04eb4643b0 feat(P6/T05): cross-framework annotation launcher JS widget
ihf-annotation-launcher.js: vanilla JS, no framework dependency. Scans DOM for
data-widget-id elements, injects Annotate trigger, opens inline form, POSTs to
/widgets/:widgetId/annotations. Works in React/Vue-rendered pages via
MutationObserver. Feature-gated by IHP_ANNOTATION_LAUNCHER=true env var
(Config.hs AnnotationLauncherEnabled, FrontController layout conditional).
Docs: docs/annotation-launcher.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 21:17:43 +00:00

80 lines
2.2 KiB
Markdown

# IHF Annotation Launcher
`static/js/ihf-annotation-launcher.js` is a self-contained vanilla JS module
that injects an **Annotate** button adjacent to every element that carries a
`data-widget-id` attribute.
It works in IHP server-rendered pages **and** in React/Vue pages where IHP does
not own the DOM — the launcher relies solely on the presence of `data-widget-id`,
not on any framework-specific structure.
## Activation
Set the environment variable before starting the server:
```bash
IHP_ANNOTATION_LAUNCHER=true devenv up
```
This causes IHP to emit the following tag in every page's `<head>`:
```html
<script src="/js/ihf-annotation-launcher.js"></script>
```
When `IHP_ANNOTATION_LAUNCHER` is absent or not `"true"`, the script is not
loaded.
## Data attributes
| Attribute | Required | Description |
|--------------------|----------|--------------------------------------------------|
| `data-widget-id` | Yes | UUID of the widget (from the widget registry) |
| `data-hub-id` | No | UUID of the hub — read from element or nearest ancestor |
| `data-view-context`| No | Logical UI location (informational) |
## Usage in React
Because the launcher uses `MutationObserver`, it will pick up React-rendered
elements after mount:
```jsx
function MyWidget({ widgetId, hubId }) {
return (
<div data-widget-id={widgetId} data-hub-id={hubId}>
<button>Do something</button>
</div>
);
}
```
No other integration is required. The launcher injects the Annotate button and
handles POST submission to `/widgets/:widgetId/annotations`.
## Programmatic re-scan
If your SPA does client-side navigation without full page reloads, call:
```js
window.IHFAnnotationLauncher.scan();
```
## Submission
The launcher POSTs `application/x-www-form-urlencoded` to:
```
POST /widgets/:widgetId/annotations
```
Fields submitted: `body`, `category`, `severity` (fixed `low`), CSRF token.
Responses:
- `200` or redirect → success (form closes with confirmation)
- Any non-OK response → inline error message
## CSRF
The launcher reads the CSRF token from `<meta name="csrf-token" content="...">`.
IHP emits this tag automatically in authenticated layouts.