@c8y/tutorial 1023.64.2 → 1023.65.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/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@c8y/tutorial",
3
- "version": "1023.64.2",
3
+ "version": "1023.65.0",
4
4
  "description": "This package is used to scaffold a tutorial for Cumulocity IoT Web SDK which explains a lot of concepts.",
5
5
  "dependencies": {
6
- "@c8y/style": "1023.64.2",
7
- "@c8y/ngx-components": "1023.64.2",
8
- "@c8y/client": "1023.64.2",
9
- "@c8y/bootstrap": "1023.64.2",
6
+ "@c8y/style": "1023.65.0",
7
+ "@c8y/ngx-components": "1023.65.0",
8
+ "@c8y/client": "1023.65.0",
9
+ "@c8y/bootstrap": "1023.65.0",
10
10
  "@angular/cdk": "^20.2.14",
11
11
  "monaco-editor": "~0.53.0",
12
12
  "ngx-bootstrap": "20.0.2",
@@ -14,8 +14,8 @@
14
14
  "rxjs": "7.8.2"
15
15
  },
16
16
  "devDependencies": {
17
- "@c8y/options": "1023.64.2",
18
- "@c8y/devkit": "1023.64.2"
17
+ "@c8y/options": "1023.65.0",
18
+ "@c8y/devkit": "1023.65.0"
19
19
  },
20
20
  "peerDependencies": {
21
21
  "@angular/common": ">=20 <21"
@@ -15,6 +15,7 @@ import { provideWidgetsResolverSample } from '../widget-resolvers';
15
15
  import { provideMapExampleNavigator } from '../maps';
16
16
  import { provideTranslationsNavigator } from '../translations';
17
17
  import { provideLazyWidget } from '../lazy-widget';
18
+ import { provideGlobalContextWidget } from '../global-context-widget';
18
19
  import { provideBreadcrumbsNavigator } from '../breadcrumbs';
19
20
  import { provideSplitViewSamples } from '../split-view';
20
21
  import { provideIconPanelExample } from '../icon-panel';
@@ -22,6 +23,7 @@ import { provideClientInterceptorSample } from '../client-interceptor';
22
23
  import { provideUserMenuSample } from '../user-menu';
23
24
  import { AlarmsModule } from '@c8y/ngx-components/alarms';
24
25
  import { BulkOperationSchedulerModule } from '@c8y/ngx-components/operations/bulk-operation-scheduler';
26
+ import { GlobalContextModule } from '@c8y/ngx-components/global-context';
25
27
  import { provideRedirectToLastRoute } from '../redirect-to-last-route';
26
28
  import { provideAPIMock } from '../__mocks';
27
29
  import { configureWidgetProviders } from '@c8y/ngx-components/widgets/widget-providers';
@@ -51,12 +53,14 @@ export const appConfig: ApplicationConfig = {
51
53
  // Get rid of a default version factory
52
54
  importProvidersFrom(VersionModule.config({ disableWebSDKPluginVersionFactory: true })),
53
55
  ...provideLazyWidget(),
56
+ ...provideGlobalContextWidget(),
54
57
  ...configureWidgetProviders(),
55
58
  ...provideRedirectToLastRoute(),
56
59
  ...provideAPIMock(),
57
60
  ...provideBreadcrumbsNavigator(),
58
61
  ...provideSplitViewSamples(),
59
62
  ...provideIconPanelExample(),
60
- importProvidersFrom(AlarmsModule.config({ hybrid: false }))
63
+ importProvidersFrom(AlarmsModule.config({ hybrid: false })),
64
+ importProvidersFrom(GlobalContextModule)
61
65
  ]
62
66
  };
@@ -0,0 +1,62 @@
1
+ import { Component } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { CoreModule, Widget } from '@c8y/ngx-components';
4
+ import { ContextDashboardModule } from '@c8y/ngx-components/context-dashboard';
5
+
6
+ /**
7
+ * Dashboard page showcasing the Global Time Context v2 widget example.
8
+ *
9
+ * This dashboard demonstrates:
10
+ * - GlobalContextConnectorComponent for dashboard mode (linked to global context)
11
+ * - LocalControlsComponent for config/view_and_config modes (local controls)
12
+ * - Time context integration with global dashboard controls in the action bar
13
+ *
14
+ * The widget responds to:
15
+ * - Time range changes (Live mode: last hour, etc. / History mode: date range)
16
+ * - Auto-refresh toggle
17
+ * - Manual refresh
18
+ * - Aggregation settings (in History mode)
19
+ */
20
+ @Component({
21
+ selector: 'c8y-global-context-dashboard',
22
+ standalone: true,
23
+ imports: [CommonModule, CoreModule, ContextDashboardModule],
24
+ template: `
25
+ <c8y-title>Global Time Context Example</c8y-title>
26
+ <c8y-context-dashboard
27
+ name="global-context-example"
28
+ [defaultWidgets]="defaultWidgets"
29
+ [canDelete]="false"
30
+ ></c8y-context-dashboard>
31
+ `
32
+ })
33
+ export class GlobalContextDashboardComponent {
34
+ defaultWidgets: Widget[] = [
35
+ {
36
+ _x: 0,
37
+ _y: 0,
38
+ _width: 6,
39
+ _height: 5,
40
+ componentId: 'tutorial.global-context-widget',
41
+ config: {
42
+ // IMPORTANT: displayMode must be 'dashboard' for GlobalContextConnector to be used.
43
+ // This tells the system that this widget is linked to the global time context.
44
+ displayMode: 'dashboard'
45
+ },
46
+ title: 'Widget 1 - Linked to Global Context',
47
+ id: 'global-context-widget-1'
48
+ },
49
+ {
50
+ _x: 6,
51
+ _y: 0,
52
+ _width: 6,
53
+ _height: 5,
54
+ componentId: 'tutorial.global-context-widget',
55
+ config: {
56
+ displayMode: 'dashboard'
57
+ },
58
+ title: 'Widget 2 - Also Linked',
59
+ id: 'global-context-widget-2'
60
+ }
61
+ ];
62
+ }
@@ -0,0 +1,35 @@
1
+ import { Component, Input, OnInit } from '@angular/core';
2
+ import { WidgetConfig } from './widget-config.model';
3
+
4
+ /**
5
+ * Widget configuration component.
6
+ *
7
+ * Note: The "Time context" section (display mode, time range, aggregation, etc.)
8
+ * is automatically added by hookWidgetConfig with GlobalContextSectionComponent.
9
+ * This component only handles widget-specific configuration.
10
+ */
11
+ @Component({
12
+ selector: 'c8y-global-context-widget-config',
13
+ standalone: true,
14
+ template: `
15
+ <div class="alert alert-info m-t-16">
16
+ <p class="m-b-0">
17
+ <strong>Note:</strong> The "Time context" section above is automatically injected via
18
+ <code>hookWidgetConfig</code> with <code>GlobalContextSectionComponent</code>. It handles:
19
+ </p>
20
+ <ul class="m-b-0 m-t-8">
21
+ <li>Display mode selection (Dashboard / Configuration / Widget view)</li>
22
+ <li>Time range configuration (Live / History)</li>
23
+ <li>Auto-refresh settings</li>
24
+ <li>Aggregation options</li>
25
+ </ul>
26
+ </div>
27
+ `
28
+ })
29
+ export class GlobalContextWidgetConfigComponent implements OnInit {
30
+ @Input() config: WidgetConfig = {};
31
+
32
+ ngOnInit() {
33
+ console.log('Widget config loaded:', this.config);
34
+ }
35
+ }
@@ -0,0 +1,331 @@
1
+ import { Component, Input, OnInit, inject, signal, computed } from '@angular/core';
2
+ import { DashboardChildComponent, DatePipe } from '@c8y/ngx-components';
3
+ import {
4
+ LocalControlsComponent,
5
+ GlobalContextConnectorComponent,
6
+ GlobalContextState,
7
+ DisplayMode,
8
+ GLOBAL_CONTEXT_DISPLAY_MODE,
9
+ REFRESH_OPTION
10
+ } from '@c8y/ngx-components/global-context';
11
+ import { WidgetConfig, WIDGET_CONTROLS } from './widget-config.model';
12
+
13
+ /**
14
+ * Example widget view component demonstrating Global Time Context v2 integration.
15
+ *
16
+ * The `displayMode` determines **where time controls come from** (not visual appearance):
17
+ *
18
+ * **Dashboard mode** (`displayMode: 'dashboard'`):
19
+ * - Time is controlled by the dashboard-level action bar (shared across all widgets)
20
+ * - Uses `GlobalContextConnectorComponent` to connect the widget to the global time context
21
+ * - All widgets on the dashboard share the same time range
22
+ *
23
+ * **Config mode** (`displayMode: 'config'`):
24
+ * - Time is controlled only in the widget configuration panel
25
+ * - Uses `LocalControlsComponent` with the widget's stored time range
26
+ * - Widget operates with a fixed, pre-configured time range at runtime
27
+ *
28
+ * **View_and_config mode** (`displayMode: 'view_and_config'`):
29
+ * - Time is controlled by inline controls rendered inside the widget itself
30
+ * - Uses `LocalControlsComponent` for independent, user-adjustable time controls
31
+ * - Widget has its own time range, not linked to other widgets
32
+ *
33
+ * Key integration points:
34
+ * - `[controls]` - Defines which features are available (live time, history, aggregation, etc.)
35
+ * - `[config]` - Current time context state (dateFrom, dateTo, aggregation, etc.)
36
+ * - `[isLoading]` - When true, pauses auto-refresh counter until loading completes
37
+ * - `(configChange)` - Emitted when user changes time context settings
38
+ * - `(refresh)` - Emitted on auto-refresh tick or manual refresh
39
+ *
40
+ * @example
41
+ * ```html
42
+ * <!-- In dashboard mode, use GlobalContextConnector -->
43
+ * <c8y-global-context-connector
44
+ * [controls]="widgetControls"
45
+ * [config]="contextConfig()"
46
+ * [isLoading]="isLoading()"
47
+ * [dashboardChild]="getDashboardChild()"
48
+ * (configChange)="onContextChange($event)"
49
+ * (refresh)="onRefresh()"
50
+ * ></c8y-global-context-connector>
51
+ * ```
52
+ */
53
+ @Component({
54
+ selector: 'c8y-global-context-widget-view',
55
+ standalone: true,
56
+ imports: [DatePipe, LocalControlsComponent, GlobalContextConnectorComponent],
57
+ template: `
58
+ <!-- Dashboard mode: Connect to global time context -->
59
+ @if (displayMode() === GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD) {
60
+ <c8y-global-context-connector
61
+ [controls]="widgetControls"
62
+ [config]="contextConfig()"
63
+ [isLoading]="isLoading()"
64
+ [dashboardChild]="getDashboardChild()"
65
+ [linked]="isLinkedToGlobal()"
66
+ (configChange)="onContextChange($event)"
67
+ (refresh)="onRefresh()"
68
+ ></c8y-global-context-connector>
69
+ } @else {
70
+ <!-- Config/View_and_config modes: Local controls -->
71
+ <c8y-local-controls
72
+ [controls]="widgetControls"
73
+ [displayMode]="displayMode()"
74
+ [config]="contextConfig()"
75
+ [isLoading]="isLoading()"
76
+ (configChange)="onContextChange($event)"
77
+ (refresh)="onRefresh()"
78
+ ></c8y-local-controls>
79
+ }
80
+
81
+ <!-- Widget content -->
82
+ <div class="p-16">
83
+ <!-- Status indicator -->
84
+ <div class="m-b-16">
85
+ <span class="text-muted small">Mode</span>
86
+ <p class="m-b-0">
87
+ <strong>{{ isLiveMode() ? 'Live' : 'History' }}</strong>
88
+ </p>
89
+ </div>
90
+
91
+ <!-- Time Range -->
92
+ @if (contextConfig().dateTimeContext; as dtc) {
93
+ <div class="row m-b-16">
94
+ <div class="col-xs-6">
95
+ <p class="text-muted small m-b-4">From</p>
96
+ <p class="text-medium m-b-0">{{ dtc.dateFrom | date: 'medium' }}</p>
97
+ </div>
98
+ <div class="col-xs-6">
99
+ <p class="text-muted small m-b-4">To</p>
100
+ <p class="text-medium m-b-0">{{ dtc.dateTo | date: 'medium' }}</p>
101
+ </div>
102
+ </div>
103
+
104
+ <!-- Settings row -->
105
+ <div class="d-flex flex-wrap p-t-8 p-b-8 separator-top">
106
+ <div class="m-r-24">
107
+ <span class="text-muted small">Duration</span>
108
+ <p class="m-b-0">
109
+ <strong>{{ formatDuration() }}</strong>
110
+ </p>
111
+ </div>
112
+ <div class="m-r-24">
113
+ <span class="text-muted small">Interval</span>
114
+ <p class="m-b-0">
115
+ <code>{{ dtc.interval || 'custom' }}</code>
116
+ </p>
117
+ </div>
118
+ @if (contextConfig().aggregation) {
119
+ <div>
120
+ <span class="text-muted small">Aggregation</span>
121
+ <p class="m-b-0">
122
+ <code>{{ contextConfig().aggregation }}</code>
123
+ </p>
124
+ </div>
125
+ }
126
+ </div>
127
+ } @else {
128
+ <p class="text-muted">Waiting for time context...</p>
129
+ }
130
+
131
+ <!-- Data fetch status -->
132
+ <div class="d-flex a-i-center p-t-8 separator-top">
133
+ @if (isLoading()) {
134
+ <i class="fa fa-spinner fa-spin m-r-8"></i>
135
+ <span>Loading...</span>
136
+ } @else {
137
+ <span class="text-muted small m-r-16"
138
+ >Last fetch: {{ lastFetchTime | date: 'mediumTime' }}</span
139
+ >
140
+ <span class="text-muted small">Fetches: {{ fetchCount }}</span>
141
+ }
142
+ </div>
143
+ </div>
144
+ `
145
+ })
146
+ export class GlobalContextWidgetViewComponent implements OnInit {
147
+ /** Reference to DashboardChildComponent, required for GlobalContextConnector */
148
+ private dashboardChild = inject(DashboardChildComponent);
149
+
150
+ /** Widget configuration passed from the dashboard */
151
+ @Input() config: WidgetConfig;
152
+
153
+ /**
154
+ * Determines where the time controls come from:
155
+ * - 'dashboard': time controlled by the dashboard action bar (shared across widgets)
156
+ * - 'config': time controlled only in the widget configuration panel (fixed at runtime)
157
+ * - 'view_and_config': time controlled by inline controls inside the widget
158
+ */
159
+ displayMode = signal<DisplayMode>(GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD);
160
+
161
+ /** Current time context state (dateTimeContext, aggregation, refreshOption, etc.) */
162
+ contextConfig = signal<GlobalContextState>({});
163
+
164
+ /**
165
+ * Controls link state to global context:
166
+ * - `true` or `undefined`: Widget follows global time context (receives all changes)
167
+ * - `false`: Widget uses local state, ignores global context changes
168
+ *
169
+ * Set to `false` when user is actively interacting with the widget
170
+ * (scrolling, zooming, selecting) to prevent global changes from
171
+ * interrupting their action. Set back to `true` when interaction ends.
172
+ */
173
+ isLinkedToGlobal = signal<boolean | undefined>(undefined);
174
+
175
+ /**
176
+ * Loading state signal. Pass this to the connector/controls.
177
+ * When `true`, the auto-refresh counter pauses until loading completes.
178
+ * This prevents data fetches from stacking up during slow API calls.
179
+ */
180
+ isLoading = signal<boolean>(false);
181
+
182
+ /** Widget controls - shared with index.ts to keep registration and runtime in sync. */
183
+ readonly widgetControls = WIDGET_CONTROLS;
184
+
185
+ /** Expose display mode constants for use in template */
186
+ readonly GLOBAL_CONTEXT_DISPLAY_MODE = GLOBAL_CONTEXT_DISPLAY_MODE;
187
+
188
+ // ─────────────────────────────────────────────────────────────────────────────
189
+ // DEMO-ONLY PROPERTIES - You can ignore these, they're just for visualization
190
+ // ─────────────────────────────────────────────────────────────────────────────
191
+
192
+ /** @ignore Demo only: Timestamp of last data fetch */
193
+ lastFetchTime: Date | null = null;
194
+
195
+ /** @ignore Demo only: Count of data fetches */
196
+ fetchCount = 0;
197
+
198
+ /** @ignore Demo only: Computed flag for Live mode display */
199
+ isLiveMode = computed(() => this.contextConfig().refreshOption === REFRESH_OPTION.LIVE);
200
+
201
+ /** @ignore Demo only: Computed flag for auto-refresh display */
202
+ isAutoRefreshActive = computed(() => this.contextConfig().isAutoRefreshEnabled === true);
203
+
204
+ // ─────────────────────────────────────────────────────────────────────────────
205
+
206
+ /**
207
+ * Initialize the widget with configuration from the dashboard.
208
+ * In dashboard mode, waits for GlobalContextConnector to emit first state.
209
+ * In other modes, fetches data immediately.
210
+ */
211
+ ngOnInit(): void {
212
+ const {
213
+ displayMode = GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD,
214
+ dateTimeContext,
215
+ aggregation,
216
+ isAutoRefreshEnabled,
217
+ refreshInterval,
218
+ refreshOption
219
+ } = this.config;
220
+
221
+ this.displayMode.set(displayMode as DisplayMode);
222
+ this.contextConfig.set({
223
+ dateTimeContext,
224
+ aggregation,
225
+ isAutoRefreshEnabled,
226
+ refreshInterval,
227
+ refreshOption
228
+ });
229
+
230
+ // In dashboard mode, GlobalContextConnector will emit the initial state
231
+ // In other modes, we need to fetch data ourselves
232
+ if (displayMode !== GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD) {
233
+ this.fetchData();
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Handle context changes from GlobalContextConnector or LocalControls.
239
+ * Called when user changes time range, aggregation, or other settings.
240
+ *
241
+ * @param event - Contains full context state and diff of what changed
242
+ */
243
+ onContextChange(event: { context: GlobalContextState; diff: GlobalContextState }): void {
244
+ const { diff, context } = event;
245
+
246
+ // Always update context config for UI reactivity
247
+ this.contextConfig.set(event.context);
248
+
249
+ // Optimization: Skip fetch if only auto-refresh was disabled in Live mode.
250
+ // In Live mode, the time window slides automatically, so we don't need to
251
+ // re-fetch just because auto-refresh was turned off.
252
+ if (
253
+ diff.isAutoRefreshEnabled === false &&
254
+ Object.keys(diff).length === 1 &&
255
+ context.refreshOption === REFRESH_OPTION.LIVE
256
+ ) {
257
+ return;
258
+ }
259
+
260
+ this.fetchData();
261
+ }
262
+
263
+ /**
264
+ * Handle refresh events (manual refresh button or auto-refresh tick).
265
+ */
266
+ onRefresh(): void {
267
+ this.fetchData();
268
+ }
269
+
270
+ /**
271
+ * Required for GlobalContextConnector - provides reference to DashboardChildComponent.
272
+ * This allows the connector to register the widget with the dashboard's context system.
273
+ */
274
+ getDashboardChild(): DashboardChildComponent {
275
+ return this.dashboardChild;
276
+ }
277
+
278
+ // ─────────────────────────────────────────────────────────────────────────────
279
+ // DEMO-ONLY METHOD - You can ignore this, it's just for visualization
280
+ // ─────────────────────────────────────────────────────────────────────────────
281
+
282
+ /**
283
+ * @ignore Demo only: Format the time range duration for display (e.g., "1h 30m", "2d 4h").
284
+ * This is not part of the Global Context integration - just a helper for this demo widget.
285
+ */
286
+ formatDuration(): string {
287
+ const dtc = this.contextConfig().dateTimeContext;
288
+ if (!dtc?.dateFrom || !dtc?.dateTo) {
289
+ return '-';
290
+ }
291
+
292
+ const diffMs = new Date(dtc.dateTo).getTime() - new Date(dtc.dateFrom).getTime();
293
+ const hours = Math.floor(diffMs / (1000 * 60 * 60));
294
+ const minutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
295
+
296
+ if (hours >= 24) {
297
+ const days = Math.floor(hours / 24);
298
+ return `${days}d ${hours % 24}h`;
299
+ }
300
+ return hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`;
301
+ }
302
+
303
+ // ─────────────────────────────────────────────────────────────────────────────
304
+
305
+ /**
306
+ * Fetch data based on current time context.
307
+ * Demonstrates proper loading state management:
308
+ * 1. Set isLoading to true (pauses auto-refresh counter)
309
+ * 2. Perform API call using contextConfig().dateTimeContext for time range
310
+ * 3. Set isLoading to false (resumes auto-refresh counter)
311
+ */
312
+ private async fetchData(): Promise<void> {
313
+ try {
314
+ this.isLoading.set(true);
315
+
316
+ // In a real widget, you would use the time context for API calls:
317
+ // const { dateFrom, dateTo } = this.contextConfig().dateTimeContext;
318
+ // const data = await this.api.getData({ dateFrom, dateTo });
319
+
320
+ // Simulate API call
321
+ await new Promise(resolve => setTimeout(resolve, 500));
322
+
323
+ this.lastFetchTime = new Date();
324
+ this.fetchCount++;
325
+ } catch (error) {
326
+ console.error('Error fetching data:', error);
327
+ } finally {
328
+ this.isLoading.set(false);
329
+ }
330
+ }
331
+ }
@@ -0,0 +1,87 @@
1
+ import { hookWidget, hookRoute, hookNavigator, NavigatorNode } from '@c8y/ngx-components';
2
+ import {
3
+ GlobalContextSectionComponent,
4
+ hookWidgetConfig
5
+ } from '@c8y/ngx-components/context-dashboard';
6
+ import { GLOBAL_CONTEXT_DASHBOARD_PATHS } from '@c8y/ngx-components/global-context';
7
+ import { gettext } from '@c8y/ngx-components/gettext';
8
+ import { WIDGET_CONTROLS } from './widget-config.model';
9
+
10
+ const WIDGET_ID = 'tutorial.global-context-widget';
11
+
12
+ /** Route path for the example dashboard */
13
+ const DASHBOARD_PATH = 'dashboard/global-context';
14
+
15
+ /**
16
+ * Provides the Global Context Widget example.
17
+ *
18
+ * This widget demonstrates the new Global Time Context v2 integration:
19
+ * - Uses GlobalContextConnectorComponent for dashboard mode
20
+ * - Uses LocalControlsComponent for config/view_and_config modes
21
+ * - Handles context changes and refresh events
22
+ * - Manages loading state to pause/resume auto-refresh
23
+ */
24
+ export function provideGlobalContextWidget() {
25
+ return [
26
+ // Register the dashboard path for Global Context support
27
+ // This enables the global context toolbar on this named dashboard route
28
+ {
29
+ provide: GLOBAL_CONTEXT_DASHBOARD_PATHS,
30
+ useValue: [DASHBOARD_PATH],
31
+ multi: true
32
+ },
33
+
34
+ // Register the widget
35
+ hookWidget({
36
+ id: WIDGET_ID,
37
+ label: gettext('Global context widget'),
38
+ description: gettext(
39
+ 'Example widget demonstrating Global Time Context v2 integration with GlobalContextConnector and LocalControls.'
40
+ ),
41
+ loadComponent: () =>
42
+ import('./global-context-widget-view.component').then(
43
+ m => m.GlobalContextWidgetViewComponent
44
+ ),
45
+ loadConfigComponent: () =>
46
+ import('./global-context-widget-config.component').then(
47
+ m => m.GlobalContextWidgetConfigComponent
48
+ ),
49
+ data: {
50
+ schema: () => import('c8y-schema-loader?interfaceName=WidgetConfig!./widget-config.model'),
51
+ // Widget controls for view component
52
+ controls: WIDGET_CONTROLS
53
+ }
54
+ }),
55
+
56
+ // Register the "Time context" configuration section
57
+ // This injects GlobalContextSectionComponent into the widget configuration panel
58
+ hookWidgetConfig<GlobalContextSectionComponent>({
59
+ widgetId: WIDGET_ID,
60
+ priority: 10,
61
+ label: gettext('Time context'),
62
+ initialState: {
63
+ controls: WIDGET_CONTROLS
64
+ },
65
+ loadComponent: () =>
66
+ import('@c8y/ngx-components/context-dashboard').then(m => m.GlobalContextSectionComponent)
67
+ }),
68
+
69
+ // Register route for the example dashboard
70
+ hookRoute({
71
+ path: DASHBOARD_PATH,
72
+ loadComponent: () =>
73
+ import('./global-context-dashboard.component').then(m => m.GlobalContextDashboardComponent)
74
+ }),
75
+
76
+ // Register navigator entry under "Dashboards"
77
+ hookNavigator(
78
+ new NavigatorNode({
79
+ label: gettext('Global context'),
80
+ path: `/${DASHBOARD_PATH}`,
81
+ icon: 'clock1',
82
+ priority: -10,
83
+ parent: 'Dashboards'
84
+ })
85
+ )
86
+ ];
87
+ }
@@ -0,0 +1,57 @@
1
+ import {
2
+ GlobalContextState,
3
+ CONTEXT_FEATURE,
4
+ PresetDefinition
5
+ } from '@c8y/ngx-components/global-context';
6
+
7
+ /**
8
+ * Widget configuration interface for the Global Context example widget.
9
+ *
10
+ * Extends `GlobalContextState` to inherit all time context properties:
11
+ * - `dateTimeContext`: Contains `dateFrom`, `dateTo`, and `interval`
12
+ * - `refreshOption`: 'live' | 'history' - determines time mode
13
+ * - `isAutoRefreshEnabled`: Whether auto-refresh is active
14
+ * - `refreshInterval`: Auto-refresh interval in milliseconds
15
+ * - `aggregation`: Data aggregation level (MINUTELY, HOURLY, DAILY)
16
+ * - `displayMode`: 'dashboard' | 'config' | 'view_and_config'
17
+ *
18
+ * These properties are automatically managed by `GlobalContextSectionComponent`
19
+ * when configured via `hookWidgetConfig`.
20
+ */
21
+ export interface WidgetConfig extends GlobalContextState {
22
+ /** Custom widget title displayed in the widget header */
23
+ title?: string;
24
+ }
25
+
26
+ /**
27
+ * Widget controls definition shared between widget registration (index.ts)
28
+ * and the view component. Defines which time context features are available
29
+ * in each display mode.
30
+ *
31
+ * Available features:
32
+ * - CONTEXT_FEATURE.LIVE_TIME - Relative time window (e.g., "last 1 hour")
33
+ * - CONTEXT_FEATURE.HISTORY_TIME - Fixed date range picker
34
+ * - CONTEXT_FEATURE.AUTO_REFRESH - Auto-refresh toggle (5s interval)
35
+ * - CONTEXT_FEATURE.AGGREGATION - Data aggregation selector
36
+ * - CONTEXT_FEATURE.REFRESH - Manual refresh button
37
+ */
38
+ export const WIDGET_CONTROLS: PresetDefinition = {
39
+ dashboard: [
40
+ CONTEXT_FEATURE.LIVE_TIME,
41
+ CONTEXT_FEATURE.HISTORY_TIME,
42
+ CONTEXT_FEATURE.AUTO_REFRESH,
43
+ CONTEXT_FEATURE.AGGREGATION
44
+ ],
45
+ config: [
46
+ CONTEXT_FEATURE.LIVE_TIME,
47
+ CONTEXT_FEATURE.HISTORY_TIME,
48
+ CONTEXT_FEATURE.AUTO_REFRESH,
49
+ CONTEXT_FEATURE.AGGREGATION
50
+ ],
51
+ view_and_config: [
52
+ CONTEXT_FEATURE.LIVE_TIME,
53
+ CONTEXT_FEATURE.HISTORY_TIME,
54
+ CONTEXT_FEATURE.AUTO_REFRESH,
55
+ CONTEXT_FEATURE.AGGREGATION
56
+ ]
57
+ };