@c8y/tutorial 1021.80.1 → 1022.3.2

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.
Files changed (86) hide show
  1. package/cumulocity.config.ts +23 -1
  2. package/package.json +13 -12
  3. package/src/__mocks/index.ts +168 -1
  4. package/src/app/app.config.ts +59 -0
  5. package/src/bootstrap.ts +13 -9
  6. package/src/bottom-drawer/bottom-drawer-content-example.component.html +28 -0
  7. package/src/bottom-drawer/bottom-drawer-content-example.component.ts +33 -0
  8. package/src/bottom-drawer/bottom-drawer-example.component.html +7 -0
  9. package/src/bottom-drawer/bottom-drawer-example.component.ts +33 -0
  10. package/src/bottom-drawer/bottom-drawer.providers.ts +17 -0
  11. package/src/breadcrumbs/index.ts +13 -1
  12. package/src/client-interceptor/index.ts +16 -1
  13. package/src/component-styles/syntactically-awesome-style-sheets-example/syntactically-awesome-style-sheets-example.component.scss +4 -2
  14. package/src/countdown/countdown-example.module.ts +1 -1
  15. package/src/dashboard/widget-guide-context-dashboard/widget-guide-context-dashboard.component.ts +1 -9
  16. package/src/date-time-range/date-time-range-example.component.ts +0 -1
  17. package/src/dynamic-forms/index.ts +13 -1
  18. package/src/grids/index.ts +13 -1
  19. package/src/grids/server-grid-example/last-updated-data-grid-column/last-updated.cell-renderer.component.ts +2 -1
  20. package/src/grids/server-grid-example/server-grid-example.component.html +2 -1
  21. package/src/grids/tree-grid-example/client-tree-grid-example.component.html +18 -0
  22. package/src/grids/tree-grid-example/client-tree-grid-example.component.ts +169 -0
  23. package/src/grids/tree-grid-example/client-tree-grid.data.ts +147 -0
  24. package/src/grids/tree-grid-example/server-tree-grid-example.component.html +30 -0
  25. package/src/grids/tree-grid-example/server-tree-grid-example.component.ts +156 -0
  26. package/src/grids/tree-grid-example/server-tree-grid-example.service.ts +255 -0
  27. package/src/grids/tree-grid-example/tree-grid-example-tab.factory.ts +31 -0
  28. package/src/grids/tree-grid-example/tree-grid-example.module.ts +36 -0
  29. package/src/hello/index.ts +18 -1
  30. package/src/hooks/action/logout-action/logout-action.component.ts +3 -4
  31. package/src/hooks/generic-wizard/minimal-setup/minimal-setup.component.ts +4 -1
  32. package/src/hooks/generic-wizard/minimal-setup/multiple-entries-one.component.ts +9 -2
  33. package/src/hooks/generic-wizard/minimal-setup/multiple-entries-two.component.ts +9 -2
  34. package/src/hooks/generic-wizard/wizard.module.ts +9 -2
  35. package/src/hooks/index.ts +13 -1
  36. package/src/hooks/navigator/index.ts +12 -1
  37. package/src/hooks/route/index.ts +42 -1
  38. package/src/hooks/stepper/basic-view/basic-view.component.ts +11 -2
  39. package/src/hooks/stepper/stepper-hook.module.ts +7 -2
  40. package/src/hooks/stepper/steps/step1.component.ts +26 -3
  41. package/src/hooks/stepper/steps/step2.component.ts +4 -1
  42. package/src/hooks/widget-config/additional-config/additional-config.component.ts +16 -0
  43. package/src/hooks/widget-config/basic-view/basic-edit.component.html +18 -0
  44. package/src/hooks/widget-config/basic-view/basic-edit.component.ts +31 -0
  45. package/src/hooks/widget-config/widget-config.providers.ts +59 -0
  46. package/src/i18n.ts +3 -0
  47. package/src/lazy/index.ts +38 -1
  48. package/src/lazy-widget/index.ts +26 -1
  49. package/src/list/index.ts +13 -1
  50. package/src/main.ts +7 -10
  51. package/src/maps/{map-examples.module.ts → index.ts} +4 -9
  52. package/src/provider-configuration/index.ts +0 -2
  53. package/src/provider-configuration/introduction-example/{introduction.module.ts → index.ts} +5 -7
  54. package/src/redirect-to-last-route/index.ts +16 -1
  55. package/src/redirect-to-last-route/redirect-to-last-route-guard.service.ts +11 -2
  56. package/src/selector/alarm-event-selector-example/alarm-event-selector.module.ts +1 -1
  57. package/src/selector/asset-selector-example/general-example/asset-selector-example.component.ts +1 -2
  58. package/src/translations/index.ts +13 -1
  59. package/src/user-menu/index.ts +23 -1
  60. package/src/widget/demo-widget-config.component.ts +11 -3
  61. package/src/widget/demo-widget.component.ts +6 -2
  62. package/src/widget/index.ts +41 -1
  63. package/src/widget-resolvers/alternative-event.resolver.ts +8 -2
  64. package/src/widget-resolvers/index.ts +47 -1
  65. package/src/widget-resolvers/widget-resolvers-config/widget-resolvers-config.component.ts +7 -3
  66. package/src/widget-resolvers/widget-resolvers.component.ts +5 -1
  67. package/src/__mocks/mock.module.ts +0 -173
  68. package/src/app/app.module.ts +0 -76
  69. package/src/breadcrumbs/breadcrumbs.module.ts +0 -14
  70. package/src/client-interceptor/client-interceptor.module.ts +0 -12
  71. package/src/dynamic-forms/dynamic-forms.module.ts +0 -16
  72. package/src/grids/grids.module.ts +0 -17
  73. package/src/hello/hello.module.ts +0 -20
  74. package/src/hooks/hooks.module.ts +0 -19
  75. package/src/hooks/navigator/navigator.module.ts +0 -21
  76. package/src/hooks/route/route.module.ts +0 -51
  77. package/src/lazy/lazy-routing.module.ts +0 -21
  78. package/src/lazy/lazy.hooks.ts +0 -24
  79. package/src/lazy-widget/lazy-widget.module.ts +0 -30
  80. package/src/list/lists.module.ts +0 -17
  81. package/src/redirect-to-last-route/redirect-to-last-route.module.ts +0 -20
  82. package/src/translations/translations.module.ts +0 -18
  83. package/src/user-menu/user-menu.module.ts +0 -13
  84. package/src/user-menu/user-menu.ts +0 -26
  85. package/src/widget/demo-widget.module.ts +0 -55
  86. package/src/widget-resolvers/widget-resolvers.module.ts +0 -52
@@ -0,0 +1,255 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { transform } from 'lodash-es';
3
+
4
+ import { IManagedObject, InventoryService, QueriesUtil } from '@c8y/client';
5
+ import {
6
+ ActionControl,
7
+ BuiltInActionType,
8
+ BulkActionControl,
9
+ Column,
10
+ Pagination
11
+ } from '@c8y/ngx-components';
12
+
13
+ import { assign, get, identity } from 'lodash-es';
14
+
15
+ /** Model for custom type filtering form. */
16
+ export interface TypeFilteringModel {
17
+ group?: boolean;
18
+ device?: boolean;
19
+ smartRule?: boolean;
20
+ dashboard?: boolean;
21
+ file?: boolean;
22
+ application?: boolean;
23
+ }
24
+
25
+ /**
26
+ * This is the example service for a data grid:
27
+ * provides the list of columns, initial pagination object, actions;
28
+ * as well as performs the query for data based on the current grid setup.
29
+ */
30
+ @Injectable()
31
+ export class ServerTreeGridExampleService {
32
+ /** This will be used to build the inventory queries. */
33
+ protected queriesUtil: QueriesUtil;
34
+
35
+ constructor(protected inventoryService: InventoryService) {
36
+ this.queriesUtil = new QueriesUtil();
37
+ }
38
+
39
+ /**
40
+ * Returns a list of columns.
41
+ * We define 2 columns with inline objects (they display simple properties
42
+ * and use default header, cell and filtring form).
43
+ * The last column is defined via a class instance (it displays a value based on
44
+ * several properties of the row item and has custom header, cell and filtering form).
45
+ */
46
+ getColumns(): Column[] {
47
+ const columns = [
48
+ {
49
+ name: 'id',
50
+ header: 'ID',
51
+ path: 'id',
52
+ filterable: true,
53
+ sortable: true
54
+ },
55
+ {
56
+ name: 'name',
57
+ header: 'Name',
58
+ path: 'name',
59
+ filterable: true,
60
+ sortable: true
61
+ }
62
+ ];
63
+
64
+ return columns;
65
+ }
66
+
67
+ /** Returns initial pagination object. */
68
+ getPagination(): Pagination {
69
+ return {
70
+ pageSize: 10,
71
+ currentPage: 1
72
+ };
73
+ }
74
+
75
+ /** Returns initial child node pagination object. */
76
+ getChildNodePagination(): Pagination {
77
+ return {
78
+ pageSize: 2,
79
+ currentPage: 1
80
+ };
81
+ }
82
+
83
+ /** Returns an array of individual row actions. */
84
+ getActionControls(): ActionControl[] {
85
+ return [
86
+ { type: BuiltInActionType.Edit, callback: item => console.dir(item) },
87
+ { type: BuiltInActionType.Export, callback: item => console.dir(item) },
88
+ { type: BuiltInActionType.Delete, callback: item => console.dir(item) },
89
+ {
90
+ type: 'customAction',
91
+ icon: 'online',
92
+ text: 'Custom action',
93
+ callback: item => console.dir(item)
94
+ }
95
+ ];
96
+ }
97
+
98
+ /** Returns an array of bulk row actions. */
99
+ getBulkActionControls(): BulkActionControl[] {
100
+ return [
101
+ {
102
+ type: BuiltInActionType.Export,
103
+ callback: selectedItemIds => console.dir(selectedItemIds)
104
+ },
105
+ {
106
+ type: BuiltInActionType.Delete,
107
+ callback: selectedItemIds => console.dir(selectedItemIds)
108
+ },
109
+ {
110
+ type: 'customAction',
111
+ icon: 'online',
112
+ iconClasses: 'm-r-4',
113
+ text: 'Custom action',
114
+ showIf: selectedItemIds => selectedItemIds?.every(id => Number.parseInt(id) % 2 === 0),
115
+ callback: selectedItemIds => console.dir(selectedItemIds)
116
+ }
117
+ ];
118
+ }
119
+
120
+ /** Returns data for current columns and pagination setup. */
121
+ async getData(columns: Column[], pagination: Pagination) {
122
+ // build filters based on columns and pagination
123
+ const filters = this.getFilters(columns, pagination);
124
+ // execute inventory query for the list of managed objects
125
+ return this.inventoryService.list(filters);
126
+ }
127
+
128
+ /** Returns the number of items matching current columns and pagination setup. */
129
+ async getCount(columns: Column[], pagination: Pagination) {
130
+ const filters = {
131
+ ...this.getFilters(columns, pagination),
132
+ withTotalElements: true
133
+ };
134
+ return (await this.inventoryService.list(filters)).paging.totalElements;
135
+ }
136
+
137
+ /** Returns the total number of items (with no filters). */
138
+ async getTotal(): Promise<number> {
139
+ const filters = {
140
+ withTotalElements: true
141
+ };
142
+ return (await this.inventoryService.list(filters)).paging.totalElements;
143
+ }
144
+
145
+ async getChildDevices(parentId: string, pagination: Pagination) {
146
+ const filters = {
147
+ ...this.getFilters([], pagination),
148
+ withChildren: false,
149
+ withChildrenCount: true
150
+ };
151
+ return this.inventoryService.childDevicesList(parentId, filters);
152
+ }
153
+
154
+ /** Returns an icon and label representing the type of the managed object. */
155
+ getTypeIconAndLabel(mo: IManagedObject): { icon: string; label: string } {
156
+ let icon = 'question';
157
+ let label = 'Other';
158
+
159
+ if (mo.type === 'c8y_DeviceGroup') {
160
+ icon = 'c8y-group';
161
+ label = 'Group';
162
+ }
163
+
164
+ if (mo.c8y_IsDevice !== undefined) {
165
+ icon = 'exchange';
166
+ label = 'Device';
167
+ }
168
+
169
+ if (mo.type === 'c8y_SmartRule' || mo.type === 'c8y_PrivateSmartRule') {
170
+ icon = 'c8y-smart-rules';
171
+ label = 'Smart rule';
172
+ }
173
+
174
+ if (mo.c8y_Dashboard !== undefined) {
175
+ icon = 'th';
176
+ label = 'Dashboard';
177
+ }
178
+
179
+ if (mo.c8y_IsBinary !== undefined) {
180
+ icon = 'file';
181
+ label = 'File';
182
+ }
183
+
184
+ if (mo.type && mo.type.startsWith('c8y_Application')) {
185
+ icon = 'c8y-atom';
186
+ label = 'Application';
187
+ }
188
+
189
+ return { icon, label };
190
+ }
191
+
192
+ /** Returns filters for given columns and pagination setup. */
193
+ private getFilters(columns: Column[], pagination: Pagination) {
194
+ return {
195
+ query: this.getQueryString(columns),
196
+ pageSize: pagination.pageSize,
197
+ currentPage: pagination.currentPage,
198
+ withChildren: false,
199
+ withChildrenCount: true,
200
+ withTotalPages: true
201
+ };
202
+ }
203
+
204
+ /** Returns a query string based on columns setup. */
205
+ private getQueryString(columns: Column[]): string {
206
+ const fullQuery = this.getQueryObj(columns);
207
+ return this.queriesUtil.buildQuery(fullQuery);
208
+ }
209
+
210
+ /** Returns a query object based on columns setup. */
211
+ private getQueryObj(columns: Column[], defaultFilter = {}): any {
212
+ return transform(columns, (query, column) => this.addColumnQuery(query, column), {
213
+ __filter: {},
214
+ __orderby: [],
215
+ ...defaultFilter
216
+ });
217
+ }
218
+
219
+ /** Extends given query with a part based on the setup of given column. */
220
+ private addColumnQuery(query: any, column: Column): void {
221
+ // when a column is marked as filterable
222
+ if (column.filterable) {
223
+ // in the case of default filtering form, `filterPredicate` will contain the string entered by a user
224
+ if (column.filterPredicate) {
225
+ // so we use it as the expected value, * allow to search for it anywhere in the property
226
+ query.__filter[column.path] = `*${column.filterPredicate}*`;
227
+ }
228
+
229
+ // in the case of custom filtering form, we're storing the query in `externalFilterQuery.query`
230
+ if (column.externalFilterQuery) {
231
+ const getFilter = column.filteringConfig.getFilter || identity;
232
+ const queryObj = getFilter(column.externalFilterQuery);
233
+
234
+ if (queryObj.__or) {
235
+ query.__filter.__and = query.__filter.__and || [];
236
+ query.__filter.__and.push(queryObj);
237
+ } else if (queryObj.__and && get(query, '__filter.__and')) {
238
+ queryObj.__and.map(obj => query.__filter.__and.push(obj));
239
+ } else {
240
+ assign(query.__filter, queryObj);
241
+ }
242
+ }
243
+ }
244
+
245
+ // when a column is sortable and has a specified sorting order
246
+ if (column.sortable && column.sortOrder) {
247
+ // add sorting condition for the configured column `path`
248
+ query.__orderby.push({
249
+ [column.path]: column.sortOrder === 'asc' ? 1 : -1
250
+ });
251
+ }
252
+
253
+ return query;
254
+ }
255
+ }
@@ -0,0 +1,31 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { Router } from '@angular/router';
3
+ import { Tab, TabFactory } from '@c8y/ngx-components';
4
+
5
+ @Injectable()
6
+ export class TreeGridTabFactory implements TabFactory {
7
+ constructor(public router: Router) {}
8
+ get() {
9
+ const tabs: Tab[] = [];
10
+ if (this.router.url.match(/grids\/tree-grid-example/g)) {
11
+ tabs.push(
12
+ {
13
+ path: 'grids/tree-grid-example/server',
14
+ label: 'Server side data',
15
+ icon: 'server',
16
+ priority: 1050,
17
+ orientation: 'horizontal'
18
+ } as Tab,
19
+ {
20
+ path: 'grids/tree-grid-example/client',
21
+ label: 'Client side data',
22
+ icon: 'house',
23
+ priority: 1000,
24
+ orientation: 'horizontal'
25
+ } as Tab
26
+ );
27
+ }
28
+
29
+ return tabs;
30
+ }
31
+ }
@@ -0,0 +1,36 @@
1
+ import { NgModule } from '@angular/core';
2
+ import {
3
+ CommonModule,
4
+ hookNavigator,
5
+ hookRoute,
6
+ hookTab,
7
+ NavigatorNode
8
+ } from '@c8y/ngx-components';
9
+ import { TreeGridTabFactory } from './tree-grid-example-tab.factory';
10
+
11
+ @NgModule({
12
+ imports: [CommonModule],
13
+ providers: [
14
+ hookRoute({
15
+ path: 'grids/tree-grid-example/server',
16
+ loadComponent: () =>
17
+ import('./server-tree-grid-example.component').then(m => m.ServerTreeGridExampleComponent)
18
+ }),
19
+ hookRoute({
20
+ path: 'grids/tree-grid-example/client',
21
+ loadComponent: () =>
22
+ import('./client-tree-grid-example.component').then(m => m.ClientGridExampleComponent)
23
+ }),
24
+ hookNavigator(
25
+ new NavigatorNode({
26
+ priority: 20,
27
+ path: 'grids/tree-grid-example/server',
28
+ icon: 'tree-structure',
29
+ label: 'Tree grid',
30
+ parent: 'Data grid examples'
31
+ })
32
+ ),
33
+ hookTab(TreeGridTabFactory)
34
+ ]
35
+ })
36
+ export class TreeGridExampleModule {}
@@ -1 +1,18 @@
1
- export * from './hello.module';
1
+ import { hookRoute } from '@c8y/ngx-components';
2
+ import { HelloComponent } from './hello.component';
3
+
4
+ export function provideHelloSample() {
5
+ return [
6
+ hookRoute([
7
+ {
8
+ path: '',
9
+ redirectTo: 'hello',
10
+ pathMatch: 'full'
11
+ },
12
+ {
13
+ path: 'hello',
14
+ component: HelloComponent
15
+ }
16
+ ])
17
+ ];
18
+ }
@@ -1,6 +1,6 @@
1
1
  import { Component } from '@angular/core';
2
2
  // eslint-disable-next-line
3
- import { CoreModule, LoginService } from '@c8y/ngx-components';
3
+ import { CoreModule, SimplifiedAuthService } from '@c8y/ngx-components';
4
4
 
5
5
  @Component({
6
6
  selector: 'app-logout-action',
@@ -11,12 +11,11 @@ import { CoreModule, LoginService } from '@c8y/ngx-components';
11
11
  imports: [CoreModule]
12
12
  })
13
13
  export class LogoutActionComponent {
14
- // Uncomment to see the effect.
15
- // constructor(private loginService: LoginService) {}
14
+ constructor(private _authService: SimplifiedAuthService) {}
16
15
 
17
16
  logout() {
18
17
  console.log('Logout action triggered!');
19
18
  // Uncomment to see the effect.
20
- // this.loginService.logout();
19
+ // this._authService.logout();
21
20
  }
22
21
  }
@@ -1,11 +1,14 @@
1
1
  import { Component } from '@angular/core';
2
+ import { WizardHeaderComponent, WizardBodyComponent } from '@c8y/ngx-components';
2
3
 
3
4
  @Component({
4
5
  selector: 'container-component',
5
6
  template: `
6
7
  <c8y-wizard-header> New header </c8y-wizard-header>
7
8
  <c8y-wizard-body> New body </c8y-wizard-body>
8
- `
9
+ `,
10
+ standalone: true,
11
+ imports: [WizardHeaderComponent, WizardBodyComponent]
9
12
  })
10
13
  export class MinimalSetupComponent {
11
14
  // In this case cancel method is not required, because it is the default button when the <c8y-wizard-footer> tag is missing.
@@ -1,5 +1,10 @@
1
1
  import { Component } from '@angular/core';
2
- import { WizardComponent } from '@c8y/ngx-components';
2
+ import {
3
+ WizardComponent,
4
+ WizardHeaderComponent,
5
+ WizardBodyComponent,
6
+ WizardFooterComponent
7
+ } from '@c8y/ngx-components';
3
8
 
4
9
  @Component({
5
10
  selector: 'multiple-entries-one-component',
@@ -10,7 +15,9 @@ import { WizardComponent } from '@c8y/ngx-components';
10
15
  <button class="btn btn-default" title="{{ 'Back' }}" (click)="back()">Back</button>
11
16
  <button class="btn btn-default" title="{{ 'Cancel' }}" (click)="cancel()">Cancel</button>
12
17
  </c8y-wizard-footer>
13
- `
18
+ `,
19
+ standalone: true,
20
+ imports: [WizardHeaderComponent, WizardBodyComponent, WizardFooterComponent]
14
21
  })
15
22
  export class MultipleEntriesOne {
16
23
  constructor(private wizardComponent: WizardComponent) {}
@@ -1,5 +1,10 @@
1
1
  import { Component } from '@angular/core';
2
- import { WizardComponent } from '@c8y/ngx-components';
2
+ import {
3
+ WizardComponent,
4
+ WizardHeaderComponent,
5
+ WizardBodyComponent,
6
+ WizardFooterComponent
7
+ } from '@c8y/ngx-components';
3
8
 
4
9
  @Component({
5
10
  selector: 'multiple-entries-two-component',
@@ -10,7 +15,9 @@ import { WizardComponent } from '@c8y/ngx-components';
10
15
  <button class="btn btn-default" title="{{ 'Back' }}" (click)="back()">Back</button>
11
16
  <button class="btn btn-default" title="{{ 'Cancel' }}" (click)="cancel()">Cancel</button>
12
17
  </c8y-wizard-footer>
13
- `
18
+ `,
19
+ standalone: true,
20
+ imports: [WizardHeaderComponent, WizardBodyComponent, WizardFooterComponent]
14
21
  })
15
22
  export class MultipleEntriesTwo {
16
23
  constructor(private wizardComponent: WizardComponent) {}
@@ -21,8 +21,15 @@ const routes: Routes = [
21
21
  ];
22
22
 
23
23
  @NgModule({
24
- declarations: [MinimalSetupComponent, MultipleEntriesOne, MultipleEntriesTwo],
25
- imports: [RouterModule.forChild(routes), CoreModule, FormsModule, ReactiveFormsModule],
24
+ imports: [
25
+ RouterModule.forChild(routes),
26
+ CoreModule,
27
+ FormsModule,
28
+ ReactiveFormsModule,
29
+ MinimalSetupComponent,
30
+ MultipleEntriesOne,
31
+ MultipleEntriesTwo
32
+ ],
26
33
  /**
27
34
  * Adding the hooks to the providers:
28
35
  */
@@ -1 +1,13 @@
1
- export * from './hooks.module';
1
+ import { hookNavigator, NavigatorNode } from '@c8y/ngx-components';
2
+
3
+ export function provideHooksSample() {
4
+ return [
5
+ hookNavigator(
6
+ new NavigatorNode({
7
+ priority: 90,
8
+ icon: 'u-turn',
9
+ label: 'Hooks'
10
+ })
11
+ )
12
+ ];
13
+ }
@@ -1 +1,12 @@
1
- export * from './navigator.module';
1
+ import { hookNavigator } from '@c8y/ngx-components';
2
+ import { ExampleNavigationFactory } from './navigator';
3
+
4
+ export function provideHooksNavigatorSample() {
5
+ /**
6
+ * Use our predefined InjectionTokens and provide your own classes to extend behavior
7
+ * and functionality of existing ones. Implement your own NavigationNodes, Tabs, Actions and Breadcrumbs.
8
+ * Note: Hooks should always be implemented in the module where they are used, so that
9
+ * a module can act standalone and has no dependencies on other modules.
10
+ */
11
+ return [hookNavigator(ExampleNavigationFactory)];
12
+ }
@@ -1 +1,42 @@
1
- export * from './route.module';
1
+ import { hookRoute, ViewContext } from '@c8y/ngx-components';
2
+ import { RandomGuard } from './random.guard';
3
+
4
+ export function provideRouteSample() {
5
+ return [
6
+ /**
7
+ * Route hooks allow you to use routes as child routes on a ViewContext. If used with a context
8
+ * the particular data is resolved automatically and the page is extended by a tab. Contexts
9
+ * are currently Application, Device, Group, Tenant and User. Note: All components used here
10
+ * needs to be used as EntryComponent!
11
+ * This example will add a device tab with all the context information as well as a randomly
12
+ * guarded context tab.
13
+ *
14
+ */
15
+ hookRoute([
16
+ {
17
+ path: 'context',
18
+ context: ViewContext.Device,
19
+ loadComponent: () =>
20
+ import('./device/device-tab-context.component').then(m => m.DeviceTabContextComponent),
21
+ label: 'Context',
22
+ priority: 1000,
23
+ icon: 'bell'
24
+ },
25
+ {
26
+ path: 'info',
27
+ context: ViewContext.Device,
28
+ loadComponent: () =>
29
+ import('./device/device-info.component').then(m => m.DeviceInfoComponent),
30
+ label: 'Info',
31
+ priority: 0,
32
+ icon: 'info',
33
+ /**
34
+ * An example of an route guard which randomly activates
35
+ * the child route. See Guards documentation from Angular
36
+ * for more details.
37
+ */
38
+ canActivate: [RandomGuard]
39
+ }
40
+ ])
41
+ ];
42
+ }
@@ -1,6 +1,13 @@
1
1
  import { Component, OnInit } from '@angular/core';
2
- import { SetupStep, StepperService, Steppers } from '@c8y/ngx-components';
2
+ import {
3
+ SetupStep,
4
+ StepperService,
5
+ Steppers,
6
+ TitleComponent,
7
+ StepperOutletComponent
8
+ } from '@c8y/ngx-components';
3
9
  import { firstValueFrom } from 'rxjs';
10
+ import { NgIf } from '@angular/common';
4
11
 
5
12
  /**
6
13
  * This is a standard angular component.
@@ -21,7 +28,9 @@ import { firstValueFrom } from 'rxjs';
21
28
  </div>
22
29
  </div>
23
30
  </div>
24
- `
31
+ `,
32
+ standalone: true,
33
+ imports: [TitleComponent, NgIf, StepperOutletComponent]
25
34
  })
26
35
  export class BasicViewComponent implements OnInit {
27
36
  readonly stepperId = Steppers.SETUP;
@@ -13,8 +13,13 @@ const routes: Routes = [
13
13
  ];
14
14
 
15
15
  @NgModule({
16
- declarations: [BasicViewComponent, Step1Component, Step2Component],
17
- imports: [RouterModule.forChild(routes), CoreModule],
16
+ imports: [
17
+ RouterModule.forChild(routes),
18
+ CoreModule,
19
+ BasicViewComponent,
20
+ Step1Component,
21
+ Step2Component
22
+ ],
18
23
  /**
19
24
  * Adding the hooks to the providers:
20
25
  */
@@ -1,7 +1,20 @@
1
1
  import { CdkStep } from '@angular/cdk/stepper';
2
2
  import { Component, OnInit } from '@angular/core';
3
- import { FormBuilder, FormGroup, Validators } from '@angular/forms';
4
- import { C8yStepper } from '@c8y/ngx-components';
3
+ import {
4
+ FormBuilder,
5
+ FormGroup,
6
+ Validators,
7
+ FormsModule,
8
+ ReactiveFormsModule
9
+ } from '@angular/forms';
10
+ import {
11
+ C8yStepper,
12
+ FormGroupComponent,
13
+ RequiredInputPlaceholderDirective,
14
+ MessagesComponent,
15
+ MessageDirective,
16
+ C8yStepperButtons
17
+ } from '@c8y/ngx-components';
5
18
 
6
19
  @Component({
7
20
  selector: 'tut-step-1-device',
@@ -22,7 +35,17 @@ import { C8yStepper } from '@c8y/ngx-components';
22
35
  (onNext)="goToNextStep($event)"
23
36
  ></c8y-stepper-buttons>
24
37
  </div>
25
- `
38
+ `,
39
+ standalone: true,
40
+ imports: [
41
+ FormGroupComponent,
42
+ FormsModule,
43
+ ReactiveFormsModule,
44
+ RequiredInputPlaceholderDirective,
45
+ MessagesComponent,
46
+ MessageDirective,
47
+ C8yStepperButtons
48
+ ]
26
49
  })
27
50
  export class Step1Component implements OnInit {
28
51
  formGroupStepOne: FormGroup;
@@ -1,4 +1,5 @@
1
1
  import { Component } from '@angular/core';
2
+ import { C8yStepperButtons } from '@c8y/ngx-components';
2
3
 
3
4
  @Component({
4
5
  selector: 'tut-step-2-device',
@@ -10,7 +11,9 @@ import { Component } from '@angular/core';
10
11
  [showButtons]="{ next: false, cancel: false, back: true, custom: false }"
11
12
  [labels]="{ back: 'Got it!' }"
12
13
  ></c8y-stepper-buttons>
13
- `
14
+ `,
15
+ standalone: true,
16
+ imports: [C8yStepperButtons]
14
17
  })
15
18
  export class Step2Component {
16
19
  close() {
@@ -0,0 +1,16 @@
1
+ import { Component } from '@angular/core';
2
+ import { CoreModule } from '@c8y/ngx-components';
3
+
4
+ /**
5
+ * This is a standard angular component.
6
+ * Obviously it does not do anything.
7
+ */
8
+ @Component({
9
+ selector: 'tut-additional-config-component',
10
+ template: 'Any additional configuration can be done here.',
11
+ standalone: true,
12
+ imports: [CoreModule]
13
+ })
14
+ export class AdditionalConfigComponent {
15
+ editComponent = false;
16
+ }
@@ -0,0 +1,18 @@
1
+ <div class="card">
2
+ <div class="card-block">
3
+ <c8y-widget-config-section
4
+ *ngFor="let section of widgetConfigService.currentSections$ | async; let i = index"
5
+ [section]="section"
6
+ ></c8y-widget-config-section>
7
+ </div>
8
+
9
+ <div class="card-block">
10
+ <label>The configuration is:</label>
11
+ <code>
12
+ <pre>
13
+ {{ widgetConfigService.currentConfig$ | async | json }}
14
+ </pre
15
+ >
16
+ </code>
17
+ </div>
18
+ </div>