@meshmakers/octo-meshboard 3.4.1450 → 3.4.1490
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +191 -1
- package/fesm2022/meshmakers-octo-meshboard.mjs +3950 -170
- package/fesm2022/meshmakers-octo-meshboard.mjs.map +1 -1
- package/package.json +1 -1
- package/types/meshmakers-octo-meshboard.d.ts +1687 -18
package/README.md
CHANGED
|
@@ -72,6 +72,76 @@ To set a Well-Known Name for a MeshBoard:
|
|
|
72
72
|
|
|
73
73
|
The Well-Known Name should be lowercase with hyphens, similar to URL slugs.
|
|
74
74
|
|
|
75
|
+
### Open in edit mode (`?edit=1`)
|
|
76
|
+
|
|
77
|
+
A `?edit=1` query parameter opens the board in edit mode once it has loaded (e.g. the "Edit"
|
|
78
|
+
action of a host's board list: `/ui/meshboards/<rtId>?edit=1`, constant
|
|
79
|
+
`MESHBOARD_EDIT_QUERY_PARAM`). It is ignored on routes with `meshBoardReadonly: true`. After
|
|
80
|
+
entering edit mode the view removes the parameter from the URL (`replaceUrl`), so a reload or a
|
|
81
|
+
copied link does not re-enter edit mode. Hosts creating boards use `newMeshBoardConfig(name)`
|
|
82
|
+
for the layout defaults (the same `MeshBoardStateService.createNewMeshBoard` uses).
|
|
83
|
+
|
|
84
|
+
### Header mode (`headerMode` / `meshBoardHeaderMode`)
|
|
85
|
+
|
|
86
|
+
How much of its header the view shows is decided by the **host page**, not by the board: the
|
|
87
|
+
same board appears with its name in a board designer list and without it on a page that
|
|
88
|
+
already names it (e.g. a Home tab under a greeting).
|
|
89
|
+
|
|
90
|
+
| Mode | Shows |
|
|
91
|
+
|------|-------|
|
|
92
|
+
| `full` (default) | Board name, description and the controls |
|
|
93
|
+
| `compact` | Only the controls (time filter, entity selectors, refresh; on editable boards also manager, settings, edit, add widget, save) in a slim row aligned right, without its own bar background |
|
|
94
|
+
| `none` | No header row — for hosts that offer their own controls |
|
|
95
|
+
|
|
96
|
+
Hints (unselected entity selectors, variable resolution errors) and the "MeshBoard Not Found" /
|
|
97
|
+
"MeshBoard Not Available" help are shown in every mode.
|
|
98
|
+
|
|
99
|
+
Bind the input when embedding the view in a template, or set the route data key when a route
|
|
100
|
+
loads the view directly (the bound input wins; unknown values fall back to `full`):
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
<mm-meshboard-view headerMode="compact"></mm-meshboard-view>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
{
|
|
108
|
+
path: "boards/:rtId",
|
|
109
|
+
loadComponent: () =>
|
|
110
|
+
import('@meshmakers/octo-meshboard').then(m => m.MeshBoardViewComponent),
|
|
111
|
+
data: { meshBoardReadonly: true, meshBoardHeaderMode: 'compact' }
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
There is deliberately no per-board setting: a board stored with "no header" would lose its
|
|
116
|
+
name in the designer, where the name is the only orientation. Exported helpers:
|
|
117
|
+
`MeshBoardHeaderMode`, `MESHBOARD_HEADER_MODE_ROUTE_DATA`, `resolveMeshBoardHeaderMode`.
|
|
118
|
+
|
|
119
|
+
### Chrome (`chrome` / `meshBoardChrome`)
|
|
120
|
+
|
|
121
|
+
Whether the view draws its own **outer frame** is also decided by the host page:
|
|
122
|
+
|
|
123
|
+
| Chrome | Draws |
|
|
124
|
+
|--------|-------|
|
|
125
|
+
| `framed` (default) | The view background, the header bar (background and bottom border) and the padding around the widget grid — for a page that is only the board |
|
|
126
|
+
| `plain` | None of these: the widgets sit directly on the host surface and line up with the host page's gutter. For hosts that already provide the surface and the gutter (e.g. a Home tab), so there is no frame inside the page and no double gutter |
|
|
127
|
+
|
|
128
|
+
The widget frames (tile border, background, shadow, header) and the gap between the widgets are
|
|
129
|
+
the same in both. Like the header mode, bind the input or set the route data key (the bound
|
|
130
|
+
input wins; unknown values fall back to `framed`). Plain usually goes together with a compact
|
|
131
|
+
header:
|
|
132
|
+
|
|
133
|
+
```html
|
|
134
|
+
<mm-meshboard-view headerMode="compact" chrome="plain"></mm-meshboard-view>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
data: { meshBoardReadonly: true, meshBoardHeaderMode: 'compact', meshBoardChrome: 'plain' }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
With `plain` the host is responsible for the gutter: a route that loads the view directly into
|
|
142
|
+
an unpadded outlet should wrap it in a padded page instead. Exported helpers: `MeshBoardChrome`,
|
|
143
|
+
`MESHBOARD_CHROME_ROUTE_DATA`, `resolveMeshBoardChrome`.
|
|
144
|
+
|
|
75
145
|
### URL Sync (`meshBoardSyncUrl`)
|
|
76
146
|
|
|
77
147
|
After the initial load and after every post-init board switch (e.g. via the
|
|
@@ -102,6 +172,29 @@ routes) never rewrite the URL. Appending an rtId to a route without an
|
|
|
102
172
|
`:rtId` variant would fall through to the app's `'**'` wildcard route (bouncing
|
|
103
173
|
the user back to home) or fail with a `NavigationError` (AB#4457).
|
|
104
174
|
|
|
175
|
+
### Pinning MeshBoards to the host navigation
|
|
176
|
+
|
|
177
|
+
The MeshBoard manager dialog offers a pin toggle per board. A pinned board is
|
|
178
|
+
meant to appear in the host application's end-user navigation (the Refinery
|
|
179
|
+
Studio Home mode lists pinned boards next to its Cockpit).
|
|
180
|
+
Pinning does not change who may *open* a board — the host's routes decide that.
|
|
181
|
+
|
|
182
|
+
The flag is stored with the other encoded board settings in the description
|
|
183
|
+
blob (`navigation: { pinned: true, order?: number }`), so no CK change is
|
|
184
|
+
needed. Host apps read it from a board's raw description:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import { readMeshBoardNavigation, compareMeshBoardNavigation } from '@meshmakers/octo-meshboard';
|
|
188
|
+
|
|
189
|
+
const pinned = boards
|
|
190
|
+
.map(b => ({ ...b, navigation: readMeshBoardNavigation(b.description) }))
|
|
191
|
+
.filter(b => b.navigation?.pinned)
|
|
192
|
+
.sort(compareMeshBoardNavigation);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`MeshBoardStateService.setMeshBoardPinned(rtId, pinned)` toggles the flag and
|
|
196
|
+
keeps every other encoded setting (variables, time filter, auto-refresh, …).
|
|
197
|
+
|
|
105
198
|
## Architecture
|
|
106
199
|
|
|
107
200
|
```
|
|
@@ -201,6 +294,15 @@ interface PieChartWidgetConfig {
|
|
|
201
294
|
}
|
|
202
295
|
```
|
|
203
296
|
|
|
297
|
+
Display rules (`utils/chart-categories.ts`): enum-style categories read as words (`RESOLVE_FAILED` →
|
|
298
|
+
"Resolve failed"); well-known state categories get the theme status colours (`--theme-status-*`,
|
|
299
|
+
then `--kendo-color-*`; e.g. Resolve failed / Error → error, Available / Online → success,
|
|
300
|
+
Pending → warning); a `left` / `right` legend moves below the chart while the widget is narrower
|
|
301
|
+
than 420 px; the 30 px plot margin is only reserved while labels are shown; legend text is 12 px.
|
|
302
|
+
The status table (`STATE_STATUS_BY_KEY`, `categoryStatus`, `humanizeCategory`, `statusColor`) is
|
|
303
|
+
exported for hosts so enum chips elsewhere read the same; the colours are resolved again on every
|
|
304
|
+
theme switch (`observeThemeChanges`: `<html data-theme|class|style>`, OS colour scheme).
|
|
305
|
+
|
|
204
306
|
### Bar Chart Widget
|
|
205
307
|
Displays data as column, bar, or stacked charts.
|
|
206
308
|
|
|
@@ -268,7 +370,8 @@ interface MarkdownWidgetConfig {
|
|
|
268
370
|
}
|
|
269
371
|
```
|
|
270
372
|
|
|
271
|
-
|
|
373
|
+
`ngx-markdown`/`marked` are loaded lazily on first render (`LazyMarkdownComponent`), so they stay out of the
|
|
374
|
+
initial bundle. No root `provideMarkdown()` is needed; if the application provides one, its configuration is used.
|
|
272
375
|
|
|
273
376
|
### Entity Card Widget
|
|
274
377
|
Displays a single runtime entity in a UML-style card.
|
|
@@ -292,6 +395,93 @@ interface EntityWithAssociationsWidgetConfig {
|
|
|
292
395
|
}
|
|
293
396
|
```
|
|
294
397
|
|
|
398
|
+
### Cockpit Widgets (AB#5558)
|
|
399
|
+
|
|
400
|
+
Platform health widgets that used to be hard-wired on the Refinery Studio's Home cockpit. They
|
|
401
|
+
have **no configurable data source** (persisted as `dataSourceType: 'static'`); they read fixed
|
|
402
|
+
platform data and run every check only for viewers with the roles / CK models it needs.
|
|
403
|
+
Registered separately — not by `provideMeshBoard()` — because they need host services:
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
providers: [
|
|
407
|
+
provideMeshBoard(),
|
|
408
|
+
provideCockpitWidgets(), // registers the 5 types + built-in checks
|
|
409
|
+
provideCockpitWidgetHost({
|
|
410
|
+
access: () => { const auth = inject(AuthorizeService); return { isInRole: r => auth.isInRole(r) }; },
|
|
411
|
+
links: () => myLinkResolver, // CockpitLinkTarget -> app URL (or null)
|
|
412
|
+
explain: () => myAssistantBridge, // optional "✦ Explain"
|
|
413
|
+
recents: () => myRecentItemsSource, // optional, feeds "Recent items"
|
|
414
|
+
messages: () => myCockpitTexts // optional translations (object or signal), AB#5622
|
|
415
|
+
}),
|
|
416
|
+
// optional host checks
|
|
417
|
+
{ provide: COCKPIT_ATTENTION_PROVIDERS, useClass: MyCheck, multi: true }
|
|
418
|
+
]
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
| Type | Label | Shows | Gate (per check / KPI) | Persisted `config` |
|
|
422
|
+
|------|-------|-------|------------------------|--------------------|
|
|
423
|
+
| `attentionList` | Attention List | Findings, errors first: CK models in ResolveFailed, adapters in error / offline > 10 min, failed pipeline executions in 24 h above a threshold, pools not registered, features enabled but not installed, plus host checks (Refinery Studio: secrets needing re-entry) | each provider: AdminPanelManagement / CommunicationManagement + `System.Communication` / TenantManagement | `{ "providerIds"?: string[], "maxItems"?: number, "showExplain"?: boolean }` — no `providerIds` = all checks, including ones added later |
|
|
424
|
+
| `adapterStatus` | Adapter Status | Adapters online / expected to run (shared rule `utils/adapter-online.ts`) | CommunicationManagement + `System.Communication` | `{ "showDetail"?: boolean }` |
|
|
425
|
+
| `ckModelState` | CK Model State | CK models available / all; ResolveFailed = error, importing = warning | AdminPanelManagement | `{ "showDetail"?: boolean }` |
|
|
426
|
+
| `recentItems` | Recent Items | The viewer's recently opened pages, entities and boards (most recent first, glyph, kind, relative time as `<time>`), real links; optional "⌘K shows the same list" | none — per user, from the host's `COCKPIT_RECENT_ITEMS`; without it "Not available" + collapsed | `{ "maxItems"?: number }` (default 8, 1–20) |
|
|
427
|
+
| `pipelineExecutions` | Pipeline Executions 24 h | Executions of all data flows, failed count, hourly sparkline (same counting as the Studio's Data Flows list) | CommunicationManagement + `System.Communication` | `{ "showDetail"?: boolean, "showSparkline"?: boolean }` |
|
|
428
|
+
|
|
429
|
+
- **Role abstraction.** The library never imports the host's auth: `COCKPIT_VIEWER_ACCESS`
|
|
430
|
+
(`isInRole(role)`) answers role checks, `CkModelService.isModelAvailable` the CK models.
|
|
431
|
+
Without the token every gated check fails closed (hidden). A KPI the viewer may not see sends no
|
|
432
|
+
request. **Builders** (`CockpitViewerAccess.isBuilder()`, host-defined) see *why* ("Needs the
|
|
433
|
+
CommunicationManagement role…" / "No health checks are available for your role"); **other
|
|
434
|
+
viewers** see a neutral "Not available" without role details, and the widget reports
|
|
435
|
+
`setWidgetHiddenForViewer(id, true)` so the board collapses it outside edit mode (empty rows
|
|
436
|
+
close up, `collapseEmptyRows`). An attention list never claims "All clear" without visible checks.
|
|
437
|
+
- **Errors** never show raw messages: tiles say "The figure could not be loaded." (details in the console).
|
|
438
|
+
- **Links.** Findings and KPI tiles carry semantic `CockpitLinkTarget`s (`adapter`, `adapters`,
|
|
439
|
+
`pool`, `pools`, `dataFlows`, `ckModels`, `tenantSettings`, `secretsReEntry`); the host's
|
|
440
|
+
`COCKPIT_LINK_RESOLVER` maps them to URLs, `null` drops the chip. Host providers may also link
|
|
441
|
+
straight to their own pages (AB#5622): `{ kind: 'route', path, queryParams? }` — `path` is a URL
|
|
442
|
+
path or router commands (`['/', tenantId, 'documents']`), navigated with `routerLink` +
|
|
443
|
+
`queryParams`; relative paths resolve against the route that renders the board. The resolver
|
|
444
|
+
sees route targets too and may return a rewritten path (e.g. with the tenant/language prefix);
|
|
445
|
+
`null` keeps `path`. Route targets stay in the app: a `path` with a URL scheme or a
|
|
446
|
+
protocol-relative start (`//host`) is dropped. `CockpitContextService.resolveLinkTarget()` returns `{ path, queryParams }`
|
|
447
|
+
for custom renderings; `resolveLink()` a URL string with the query appended.
|
|
448
|
+
- **Counts.** `AttentionFinding.count?: number` (AB#5622) renders a badge next to the title
|
|
449
|
+
(formatted in `numberLocale`); without it nothing changes. Of the built-in checks only "Failed
|
|
450
|
+
pipeline executions" sets it — the others name the count in their titles.
|
|
451
|
+
- **Texts (i18n, AB#5622).** Every widget text (severity chips, empty / loading / unavailable
|
|
452
|
+
states, KPI labels, statuses and details, recent-items wording and relative times) comes from
|
|
453
|
+
`CockpitWidgetMessages` with English defaults (`DEFAULT_COCKPIT_WIDGET_MESSAGES`). Provide a
|
|
454
|
+
`Partial<CockpitWidgetMessages>` — or a `Signal` of one to follow a runtime language switch —
|
|
455
|
+
on `COCKPIT_WIDGET_MESSAGES` (or `provideCockpitWidgetHost({ messages })`); a widget used on its
|
|
456
|
+
own also takes a `messages` input. `{count}`-style placeholders; missing members keep English;
|
|
457
|
+
`numberLocale` (default `en-US`) formats the figures. `CockpitKpiService.kpi(kind, messages?)`
|
|
458
|
+
builds KPI texts the same way. Not covered: the config dialogs and the findings of the built-in
|
|
459
|
+
OctoMesh checks except "Failed pipeline executions" (`attentionFailedExecutions*`, optional
|
|
460
|
+
members); a host's own providers bring their own translated titles and texts. Nothing of
|
|
461
|
+
this is persisted — the board JSON is unchanged.
|
|
462
|
+
- **Adding a check.** Implement `AttentionProvider` (`id` — persisted, never rename — `label`,
|
|
463
|
+
`description`, `isVisible` via `CockpitContextService.allows(roles, models)`, `load` = exactly one
|
|
464
|
+
query emitting findings once) and register it on `COCKPIT_ATTENTION_PROVIDERS`.
|
|
465
|
+
- **Failed pipeline executions** (`pipeline-executions-failed`, AB#5622). Same request and
|
|
466
|
+
counting as the "Pipeline executions 24 h" KPI. Warning from `minFailed` failures (default 10),
|
|
467
|
+
error from `errorFailed` failures (default 1,000) or a failure share of `errorRatio` (default
|
|
468
|
+
0.2); `null` disables an error rule. Override with `{ provide: COCKPIT_FAILED_EXECUTIONS_OPTIONS,
|
|
469
|
+
useValue: { minFailed: 50 } }`. Links to `dataFlows` (the list has no "failed only" filter).
|
|
470
|
+
- **Data.** Lean documents with explicit fields in `graphQL/cockpit*.graphql`; the adapter states
|
|
471
|
+
and the data flow executions are shared per tenant for 10 s between the KPI and the attention
|
|
472
|
+
list (`CockpitAdapterStatesService`, `CockpitDataFlowExecutionsService`).
|
|
473
|
+
- **Recent items source.** `CockpitRecentItemsSource` = `items(limit)` (most recent first, only
|
|
474
|
+
entries the viewer may still open, each with a real `href`), `open(item)` for plain left clicks
|
|
475
|
+
(modified clicks stay with the browser), optional `revision` signal (re-read on change),
|
|
476
|
+
`openPalette()` + `paletteShortcut`. The Refinery Studio feeds it from the same history as the
|
|
477
|
+
empty Cmd+K palette. `recentItems` is not one of `COCKPIT_WIDGET_TYPES` (the health widgets).
|
|
478
|
+
- **Seeded board.** octo-platform-services' `System.UI.TenantCockpit` blueprint (≥ 1.1.0) seeds the
|
|
479
|
+
four health widgets on every tenant's `cockpit` board, since 1.3.0 also "Recently opened"
|
|
480
|
+
(`recentItems`, 3 columns) next to the CK-model pie (3 columns); `cockpit-widget-registrations.spec.ts` pins the
|
|
481
|
+
seed's encoding against `toPersistedConfig`.
|
|
482
|
+
- **Theming.** Neutral defaults via `--mm-cockpit-*` custom properties (text, text-muted, surface,
|
|
483
|
+
border, border-strong, success, warning, error, info, neutral, accent, ai) falling back to Kendo colours.
|
|
484
|
+
|
|
295
485
|
### Process Widget
|
|
296
486
|
Provides HMI-style (Human-Machine Interface) process visualization with tanks, pipes, valves, pumps, and other process elements. Includes a visual drag-and-drop designer.
|
|
297
487
|
|