@meshmakers/octo-meshboard 3.4.1480 → 3.5.0
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 +244 -1
- package/fesm2022/meshmakers-octo-meshboard.mjs +5106 -200
- package/fesm2022/meshmakers-octo-meshboard.mjs.map +1 -1
- package/package.json +1 -1
- package/types/meshmakers-octo-meshboard.d.ts +2216 -20
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
|
```
|
|
@@ -185,6 +278,29 @@ interface TableWidgetConfig {
|
|
|
185
278
|
}
|
|
186
279
|
```
|
|
187
280
|
|
|
281
|
+
**Texts (AB#5622).** The list inside the table (`mm-list-view`) takes its texts from
|
|
282
|
+
`MESHBOARD_MESSAGES` — "No records available.", pager texts, toolbar labels — merged over the
|
|
283
|
+
English defaults; the host sets them once (fixed object or a signal for a runtime language switch):
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
providers: [
|
|
287
|
+
provideMeshBoard({ messages: { tableList: { noRecords: 'Keine Einträge vorhanden.', pagerItemsPerPage: 'Einträge pro Seite' } } }),
|
|
288
|
+
// or, when the widgets are registered lazily (no provideMeshBoard()):
|
|
289
|
+
provideMeshBoardMessages(appMeshBoardMessages),
|
|
290
|
+
]
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
`tableNotConfigured` translates the placeholder of an unconfigured table.
|
|
294
|
+
|
|
295
|
+
**Enum labels (AB#5622).** `MESHBOARD_LABEL_RESOLVER` (same pattern as the entity forms'
|
|
296
|
+
`ENTITY_FORM_LABEL_RESOLVER`) translates enum values: `(request) => string | null | undefined`
|
|
297
|
+
with `request = { kind: 'tableCell' | 'chartCategory', ckTypeId?, attribute, value, valueType?,
|
|
298
|
+
defaultText }`; `null` / `undefined` / `''` keep `defaultText` (today's text), a throwing resolver
|
|
299
|
+
is logged once and ignored. Tables offer string cells of text columns (persistent-query columns
|
|
300
|
+
only when their value type is `ENUM`); pie / donut charts offer every category — the resolved text
|
|
301
|
+
is the slice name in data labels, legend and tooltips, the status colour still follows the raw
|
|
302
|
+
value. A resolver that reads a signal re-labels the charts when it changes.
|
|
303
|
+
|
|
188
304
|
### Pie Chart Widget
|
|
189
305
|
Displays data as pie or donut chart.
|
|
190
306
|
|
|
@@ -198,9 +314,34 @@ interface PieChartWidgetConfig {
|
|
|
198
314
|
showLegend?: boolean;
|
|
199
315
|
legendPosition?: 'top' | 'bottom' | 'left' | 'right';
|
|
200
316
|
filters?: WidgetFilterConfig[];
|
|
317
|
+
categoryColors?: Record<string, string>; // AB#5622
|
|
318
|
+
labelPosition?: 'inside' | 'outside' | 'none'; // AB#5622
|
|
319
|
+
hideLabelsBelowPercent?: number; // AB#5622
|
|
201
320
|
}
|
|
202
321
|
```
|
|
203
322
|
|
|
323
|
+
Colours and labels (AB#5622): every slice gets an explicit colour — a `categoryColors` entry
|
|
324
|
+
(key = raw category value, case-insensitive, or the displayed label; value = hex / CSS colour,
|
|
325
|
+
custom property `--brand-paid` / `var(--brand-paid, #2fb37a)`, or a status name `success` /
|
|
326
|
+
`warning` / `error` / `info`), else the status colour of a well-known state, else the theme
|
|
327
|
+
palette colour of its position (`chartSeriesColors()`: `--theme-chart-1…12`, then
|
|
328
|
+
`--kendo-chart-series-1…12`, then `--kendo-color-series-a…f`, then a fixed palette; unresolved or
|
|
329
|
+
invalid tokens are skipped, so no slice falls back to black in dark mode). The palette is part of
|
|
330
|
+
the theme signature, so a live theme switch re-colours the chart without a redraw loop.
|
|
331
|
+
`labelPosition` (labels mode only) maps to Kendo `outsideEnd` (theme-coloured connector lines) /
|
|
332
|
+
`insideEnd` / hidden; `hideLabelsBelowPercent` drops the labels of small slices so neighbours do
|
|
333
|
+
not overlap. All three are optional, written to the board JSON only when set, and edited in the
|
|
334
|
+
config dialog (Label Position, Hide labels below, Category Colours).
|
|
335
|
+
|
|
336
|
+
Display rules (`utils/chart-categories.ts`): enum-style categories read as words (`RESOLVE_FAILED` →
|
|
337
|
+
"Resolve failed"); well-known state categories get the theme status colours (`--theme-status-*`,
|
|
338
|
+
then `--kendo-color-*`; e.g. Resolve failed / Error → error, Available / Online → success,
|
|
339
|
+
Pending → warning); a `left` / `right` legend moves below the chart while the widget is narrower
|
|
340
|
+
than 420 px; the 30 px plot margin is only reserved while labels are shown; legend text is 12 px.
|
|
341
|
+
The status table (`STATE_STATUS_BY_KEY`, `categoryStatus`, `humanizeCategory`, `statusColor`) is
|
|
342
|
+
exported for hosts so enum chips elsewhere read the same; the colours are resolved again on every
|
|
343
|
+
theme switch (`observeThemeChanges`: `<html data-theme|class|style>`, OS colour scheme).
|
|
344
|
+
|
|
204
345
|
### Bar Chart Widget
|
|
205
346
|
Displays data as column, bar, or stacked charts.
|
|
206
347
|
|
|
@@ -268,7 +409,8 @@ interface MarkdownWidgetConfig {
|
|
|
268
409
|
}
|
|
269
410
|
```
|
|
270
411
|
|
|
271
|
-
|
|
412
|
+
`ngx-markdown`/`marked` are loaded lazily on first render (`LazyMarkdownComponent`), so they stay out of the
|
|
413
|
+
initial bundle. No root `provideMarkdown()` is needed; if the application provides one, its configuration is used.
|
|
272
414
|
|
|
273
415
|
### Entity Card Widget
|
|
274
416
|
Displays a single runtime entity in a UML-style card.
|
|
@@ -292,6 +434,107 @@ interface EntityWithAssociationsWidgetConfig {
|
|
|
292
434
|
}
|
|
293
435
|
```
|
|
294
436
|
|
|
437
|
+
### Cockpit Widgets (AB#5558)
|
|
438
|
+
|
|
439
|
+
Platform health widgets that used to be hard-wired on the Refinery Studio's Home cockpit. They
|
|
440
|
+
have **no configurable data source** (persisted as `dataSourceType: 'static'`); they read fixed
|
|
441
|
+
platform data and run every check only for viewers with the roles / CK models it needs.
|
|
442
|
+
Registered separately — not by `provideMeshBoard()` — because they need host services:
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
providers: [
|
|
446
|
+
provideMeshBoard(),
|
|
447
|
+
provideCockpitWidgets(), // registers the 5 types + built-in checks
|
|
448
|
+
provideCockpitWidgetHost({
|
|
449
|
+
access: () => { const auth = inject(AuthorizeService); return { isInRole: r => auth.isInRole(r) }; },
|
|
450
|
+
links: () => myLinkResolver, // CockpitLinkTarget -> app URL (or null)
|
|
451
|
+
explain: () => myAssistantBridge, // optional "✦ Explain"
|
|
452
|
+
recents: () => myRecentItemsSource, // optional, feeds "Recent items"
|
|
453
|
+
messages: () => myCockpitTexts // optional translations (object or signal), AB#5622
|
|
454
|
+
}),
|
|
455
|
+
// optional host checks
|
|
456
|
+
{ provide: COCKPIT_ATTENTION_PROVIDERS, useClass: MyCheck, multi: true }
|
|
457
|
+
]
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
| Type | Label | Shows | Gate (per check / KPI) | Persisted `config` |
|
|
461
|
+
|------|-------|-------|------------------------|--------------------|
|
|
462
|
+
| `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, deployment sites not registered (provider id `pools-unregistered`, kept stable for persisted `providerIds`), 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 |
|
|
463
|
+
| `adapterStatus` | Adapter Status | Adapters online / expected to run (shared rule `utils/adapter-online.ts`) | CommunicationManagement + `System.Communication` | `{ "showDetail"?: boolean }` |
|
|
464
|
+
| `ckModelState` | CK Model State | CK models available / all; ResolveFailed = error, importing = warning | AdminPanelManagement | `{ "showDetail"?: boolean }` |
|
|
465
|
+
| `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) |
|
|
466
|
+
| `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 }` |
|
|
467
|
+
| `tenantCount` | Tenants | Child tenants of the tenant (on the system tenant: all tenants), first ids; links `tenants` | TenantManagement | `{ "showDetail"?: boolean }` |
|
|
468
|
+
| `blueprintUpdates` | Blueprint Updates | Installed blueprints with a newer catalog version (warning); service-managed `System.*` ones only in the detail; links `blueprints` | AdminPanelManagement | `{ "showDetail"?: boolean }` |
|
|
469
|
+
| `servicesHealth` | Services Healthy | Identity, Asset Repository, Bot, Communication Controller (when installed) healthy / all; unhealthy or silent = error, degraded = warning; links `serviceHealth` of the first problem | none | `{ "showDetail"?: boolean }` |
|
|
470
|
+
| `versionInfo` | Version | The host's versions (`COCKPIT_VERSION_SOURCE` / `provideCockpitWidgetHost({ versions })`), first = value; no link | none — without the source "Not available" + collapsed | `{ "showDetail"?: boolean }` |
|
|
471
|
+
|
|
472
|
+
- **Role abstraction.** The library never imports the host's auth: `COCKPIT_VIEWER_ACCESS`
|
|
473
|
+
(`isInRole(role)`) answers role checks, `CkModelService.isModelAvailable` the CK models.
|
|
474
|
+
Without the token every gated check fails closed (hidden). A KPI the viewer may not see sends no
|
|
475
|
+
request. **Builders** (`CockpitViewerAccess.isBuilder()`, host-defined) see *why* ("Needs the
|
|
476
|
+
CommunicationManagement role…" / "No health checks are available for your role"); **other
|
|
477
|
+
viewers** see a neutral "Not available" without role details, and the widget reports
|
|
478
|
+
`setWidgetHiddenForViewer(id, true)` so the board collapses it outside edit mode (empty rows
|
|
479
|
+
close up, `collapseEmptyRows`). An attention list never claims "All clear" without visible checks.
|
|
480
|
+
- **Errors** never show raw messages: tiles say "The figure could not be loaded." (details in the console).
|
|
481
|
+
- **Links.** Findings and KPI tiles carry semantic `CockpitLinkTarget`s (`adapter`, `adapters`,
|
|
482
|
+
`deployment-site`, `deployment-sites`, `dataFlows`, `ckModels`, `tenantSettings`, `secretsReEntry`;
|
|
483
|
+
`pool` / `pools` are the deprecated pre-System.Communication-4.x aliases); the host's
|
|
484
|
+
`COCKPIT_LINK_RESOLVER` maps them to URLs, `null` drops the chip. When the resolver answers `null`
|
|
485
|
+
for a deployment-site kind, the context asks once more with the legacy alias
|
|
486
|
+
(`legacyCockpitLinkTarget`), so hosts that only map `pool` / `pools` keep their links (AB#5842). Host providers may also link
|
|
487
|
+
straight to their own pages (AB#5622): `{ kind: 'route', path, queryParams? }` — `path` is a URL
|
|
488
|
+
path or router commands (`['/', tenantId, 'documents']`), navigated with `routerLink` +
|
|
489
|
+
`queryParams`; relative paths resolve against the route that renders the board. The resolver
|
|
490
|
+
sees route targets too and may return a rewritten path (e.g. with the tenant/language prefix);
|
|
491
|
+
`null` keeps `path`. Route targets stay in the app: a `path` with a URL scheme or a
|
|
492
|
+
protocol-relative start (`//host`) is dropped. `CockpitContextService.resolveLinkTarget()` returns `{ path, queryParams }`
|
|
493
|
+
for custom renderings; `resolveLink()` a URL string with the query appended.
|
|
494
|
+
- **Counts.** `AttentionFinding.count?: number` (AB#5622) renders a badge next to the title
|
|
495
|
+
(formatted in `numberLocale`); without it nothing changes. Of the built-in checks only "Failed
|
|
496
|
+
pipeline executions" sets it — the others name the count in their titles.
|
|
497
|
+
- **Texts (i18n, AB#5622).** Every widget text (severity chips, empty / loading / unavailable
|
|
498
|
+
states, KPI labels, statuses and details, recent-items wording and relative times) comes from
|
|
499
|
+
`CockpitWidgetMessages` with English defaults (`DEFAULT_COCKPIT_WIDGET_MESSAGES`). Provide a
|
|
500
|
+
`Partial<CockpitWidgetMessages>` — or a `Signal` of one to follow a runtime language switch —
|
|
501
|
+
on `COCKPIT_WIDGET_MESSAGES` (or `provideCockpitWidgetHost({ messages })`); a widget used on its
|
|
502
|
+
own also takes a `messages` input. `{count}`-style placeholders; missing members keep English;
|
|
503
|
+
`numberLocale` (default `en-US`) formats the figures. `CockpitKpiService.kpi(kind, messages?)`
|
|
504
|
+
builds KPI texts the same way. Not covered: the config dialogs and the findings of the built-in
|
|
505
|
+
OctoMesh checks except "Failed pipeline executions" (`attentionFailedExecutions*`, optional
|
|
506
|
+
members); a host's own providers bring their own translated titles and texts. Nothing of
|
|
507
|
+
this is persisted — the board JSON is unchanged.
|
|
508
|
+
- **Adding a check.** Implement `AttentionProvider` (`id` — persisted, never rename — `label`,
|
|
509
|
+
`description`, `isVisible` via `CockpitContextService.allows(roles, models)`, `load` = exactly one
|
|
510
|
+
query emitting findings once) and register it on `COCKPIT_ATTENTION_PROVIDERS`.
|
|
511
|
+
- **Failed pipeline executions** (`pipeline-executions-failed`, AB#5622). Same request and
|
|
512
|
+
counting as the "Pipeline executions 24 h" KPI. Warning from `minFailed` failures (default 10),
|
|
513
|
+
error from `errorFailed` failures (default 1,000) or a failure share of `errorRatio` (default
|
|
514
|
+
0.2); `null` disables an error rule. Override with `{ provide: COCKPIT_FAILED_EXECUTIONS_OPTIONS,
|
|
515
|
+
useValue: { minFailed: 50 } }`. Links to `dataFlows` (the list has no "failed only" filter).
|
|
516
|
+
- **System cockpit checks** (AB#5558). `services-unhealthy` (one finding per platform service
|
|
517
|
+
that is not Healthy, links `serviceHealth`) and `blueprint-updates` (info, count badge, links
|
|
518
|
+
`blueprints`; AdminPanelManagement) are visible on the system tenant only
|
|
519
|
+
(`CockpitContextService.isSystemTenant`, from `systemTenantId` of the platform configuration,
|
|
520
|
+
`octosystem` without it) — tenant cockpits are unchanged. Texts: `attentionService*`,
|
|
521
|
+
`attentionBlueprintUpdates*`, `kpiTenants*`, `kpiBlueprints*`, `kpiServices*`, `kpiVersion*`
|
|
522
|
+
(optional members). Seeded by `System.UI.SystemCockpit` ≥ 1.1.0.
|
|
523
|
+
- **Data.** Lean documents with explicit fields in `graphQL/cockpit*.graphql`; the adapter states
|
|
524
|
+
and the data flow executions are shared per tenant for 10 s between the KPI and the attention
|
|
525
|
+
list (`CockpitAdapterStatesService`, `CockpitDataFlowExecutionsService`).
|
|
526
|
+
- **Recent items source.** `CockpitRecentItemsSource` = `items(limit)` (most recent first, only
|
|
527
|
+
entries the viewer may still open, each with a real `href`), `open(item)` for plain left clicks
|
|
528
|
+
(modified clicks stay with the browser), optional `revision` signal (re-read on change),
|
|
529
|
+
`openPalette()` + `paletteShortcut`. The Refinery Studio feeds it from the same history as the
|
|
530
|
+
empty Cmd+K palette. `recentItems` is not one of `COCKPIT_WIDGET_TYPES` (the health widgets).
|
|
531
|
+
- **Seeded board.** octo-platform-services' `System.UI.TenantCockpit` blueprint (≥ 1.1.0) seeds the
|
|
532
|
+
four health widgets on every tenant's `cockpit` board, since 1.3.0 also "Recently opened"
|
|
533
|
+
(`recentItems`, 3 columns) next to the CK-model pie (3 columns); `cockpit-widget-registrations.spec.ts` pins the
|
|
534
|
+
seed's encoding against `toPersistedConfig`.
|
|
535
|
+
- **Theming.** Neutral defaults via `--mm-cockpit-*` custom properties (text, text-muted, surface,
|
|
536
|
+
border, border-strong, success, warning, error, info, neutral, accent, ai) falling back to Kendo colours.
|
|
537
|
+
|
|
295
538
|
### Process Widget
|
|
296
539
|
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
540
|
|