@c8y/tutorial 1020.40.1 → 1021.0.11

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 (28) hide show
  1. package/cumulocity.config.ts +7 -1
  2. package/package.json +11 -11
  3. package/public/favicon.ico +0 -0
  4. package/src/__mocks/global-mocks/inventory.interceptor.ts +3 -0
  5. package/src/__mocks/mock.module.ts +15 -4
  6. package/src/__mocks/scoped-mocks/typeahead.ts +70 -0
  7. package/src/app/app.module.ts +0 -2
  8. package/src/dynamic-forms/json-schema-example/json-schema-example.component.ts +10 -8
  9. package/src/grids/server-grid-example/server-grid-example.component.ts +8 -4
  10. package/src/hooks/tabs/awesome/awesome.component.html +1 -1
  11. package/src/hooks/tabs/inline/inline-one.component.ts +13 -0
  12. package/src/hooks/tabs/inline/inline-two.component.ts +13 -0
  13. package/src/hooks/tabs/inline/inline.module.ts +26 -0
  14. package/src/hooks/tabs/outstanding/outstanding.component.html +13 -2
  15. package/src/hooks/tabs/outstanding/outstanding.component.ts +2 -1
  16. package/src/hooks/tabs/tab.ts +20 -4
  17. package/src/hooks/tabs/tabs.module.ts +18 -13
  18. package/src/i18n.ts +1 -1
  19. package/src/main.ts +5 -10
  20. package/src/selector/alarm-event-selector-example/alarm-event-selector.component.ts +5 -2
  21. package/src/selector/datapoint-selection-example/general-example/datapoint-selection-example.component.ts +2 -2
  22. package/src/typeahead/typeahead-example.component.html +45 -0
  23. package/src/typeahead/typeahead-example.component.ts +49 -0
  24. package/src/typeahead/typeahead-example.module.ts +19 -0
  25. package/src/dashboard-tabs/dashboard-tabs.component.ts +0 -95
  26. package/src/dashboard-tabs/dashboard-tabs.module.ts +0 -20
  27. package/src/dashboard-tabs/index.ts +0 -1
  28. package/src/favicon.ico +0 -0
@@ -729,6 +729,13 @@ export default {
729
729
  path: './src/pagination/pagination-example.module.ts',
730
730
  description: 'This is an example for pagination.',
731
731
  scope: 'self'
732
+ },
733
+ {
734
+ name: 'Typeahead',
735
+ module: 'TypeaheadExampleModule',
736
+ path: './src/typeahead/typeahead-example.module.ts',
737
+ description: 'This is an example for the typeahead component.',
738
+ scope: 'self'
732
739
  }
733
740
  ]
734
741
  },
@@ -742,7 +749,6 @@ export default {
742
749
  },
743
750
  // The embedded.css is used by codex for iframe embeddings.
744
751
  copy: [{ from: './node_modules/@c8y/style/embedded.css', to: './embedded.css' }],
745
- brandingEntry: './src/branding/branding.less',
746
752
  federation: [
747
753
  '@angular/animations',
748
754
  '@angular/cdk',
package/package.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "name": "@c8y/tutorial",
3
- "version": "1020.40.1",
3
+ "version": "1021.0.11",
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": "1020.40.1",
7
- "@c8y/ngx-components": "1020.40.1",
8
- "@c8y/client": "1020.40.1",
9
- "@c8y/bootstrap": "1020.40.1",
10
- "@angular/cdk": "^17.3.9",
11
- "ngx-bootstrap": "12.0.0",
6
+ "@c8y/style": "1021.0.11",
7
+ "@c8y/ngx-components": "1021.0.11",
8
+ "@c8y/client": "1021.0.11",
9
+ "@c8y/bootstrap": "1021.0.11",
10
+ "@angular/cdk": "^18.2.10",
11
+ "ngx-bootstrap": "18.0.0",
12
12
  "leaflet": "1.9.4",
13
- "rxjs": "^7.4.0"
13
+ "rxjs": "^7.8.1"
14
14
  },
15
15
  "devDependencies": {
16
- "@c8y/options": "1020.40.1",
17
- "@c8y/devkit": "1020.40.1"
16
+ "@c8y/options": "1021.0.11",
17
+ "@c8y/devkit": "1021.0.11"
18
18
  },
19
19
  "peerDependencies": {
20
- "@angular/common": ">=16 <18"
20
+ "@angular/common": ">=18 <19"
21
21
  },
22
22
  "author": "Cumulocity GmbH"
23
23
  }
Binary file
@@ -94,6 +94,9 @@ export class InventoryInterceptor implements HttpInterceptor {
94
94
  c8y_IsAssetType: () => ({
95
95
  managedObjects: [generateAssetType()]
96
96
  }),
97
+ c8yAssetTypesCacheInvalidator: () => ({
98
+ managedObjects: [generateRandomMo()]
99
+ }),
97
100
  c8y_IsDeviceGroup: () => ({
98
101
  managedObjects: [
99
102
  ...[...Array(5)].map(() => (Math.random() < 0.5 ? generateSubGroup() : generateAsset()))
@@ -10,14 +10,15 @@ import {
10
10
  import { InventoryInterceptor } from './global-mocks/inventory.interceptor';
11
11
  import { MeasurementsInterceptor } from './global-mocks/measurements.interceptor';
12
12
  import { API_MOCK_CONFIG, ApiMockConfig } from './mock.model';
13
+ import { RealtimeSubjectServiceWithMocking } from './mock.realtime';
13
14
  import { MockService } from './mock.service';
14
- import { NamedContextDashboardInterceptor } from './scoped-mocks/named-context-dashboard';
15
15
  import { ContextDashboardInterceptor } from './scoped-mocks/context-dashboard';
16
- import { ServerSideDataGridInterceptor } from './scoped-mocks/server-side-data-grid';
17
16
  import { DeviceDataGridInterceptor } from './scoped-mocks/device-data-grid';
18
- import { ServiceDashboardInterceptor } from './scoped-mocks/service-dashboard';
19
- import { RealtimeSubjectServiceWithMocking } from './mock.realtime';
20
17
  import { ListsInterceptor } from './scoped-mocks/lists';
18
+ import { NamedContextDashboardInterceptor } from './scoped-mocks/named-context-dashboard';
19
+ import { ServerSideDataGridInterceptor } from './scoped-mocks/server-side-data-grid';
20
+ import { ServiceDashboardInterceptor } from './scoped-mocks/service-dashboard';
21
+ import { TypeaheadInterceptor } from './scoped-mocks/typeahead';
21
22
  // import { BoilerplateInterceptor } from './scoped-mocks/boilerplate';
22
23
  @NgModule({
23
24
  imports: [CoreModule, CommonModule],
@@ -63,6 +64,16 @@ import { ListsInterceptor } from './scoped-mocks/lists';
63
64
  } as ApiMockConfig,
64
65
  multi: true
65
66
  },
67
+ {
68
+ provide: API_MOCK_CONFIG,
69
+ useValue: {
70
+ id: 'typeahaed-interceptor',
71
+ path: 'typeahead',
72
+ mockService: TypeaheadInterceptor,
73
+ debug: true
74
+ } as ApiMockConfig,
75
+ multi: true
76
+ },
66
77
  {
67
78
  provide: API_MOCK_CONFIG,
68
79
  useValue: {
@@ -0,0 +1,70 @@
1
+ import { IFetchResponse } from '@c8y/client';
2
+ import { ApiCall, HttpHandler, HttpInterceptor } from '@c8y/ngx-components/api';
3
+ import { generateResponse, handleRequest } from '../utils/common';
4
+ import { Observable } from 'rxjs';
5
+ import { generateDevice } from '../utils/generators/managedObjects';
6
+ import { filterObjects } from '../utils/grid';
7
+
8
+ export class TypeaheadInterceptor implements HttpInterceptor {
9
+ intercept(req: ApiCall, next: HttpHandler): Observable<IFetchResponse> {
10
+ return handleRequest(req, next, 'inventory/managedObjects', {
11
+ POST: this.mockPOST.bind(this),
12
+ PUT: this.mockPUT.bind(this),
13
+ GET: this.mockGET.bind(this)
14
+ });
15
+ }
16
+
17
+ mockPOST(_requestDescriptor: string) {
18
+ return null;
19
+ }
20
+
21
+ mockPUT(_requestDescriptor: string) {
22
+ return null;
23
+ }
24
+
25
+ private async mockGET(_requestDescriptor: string) {
26
+ // extra long timeout, to show the usage of c8yFor
27
+ await new Promise(r => setTimeout(r, 100));
28
+
29
+ const responseGenerators = this.getResponseGenerators();
30
+
31
+ for (const urlPart in responseGenerators) {
32
+ if (_requestDescriptor.includes(urlPart)) {
33
+ const pageSize = _requestDescriptor.match(/\"pageSize\"\:(\d+)/)
34
+ ? parseInt(_requestDescriptor.match(/\"pageSize\"\:(\d+)/)[1])
35
+ : null;
36
+
37
+ const generatorResult = responseGenerators[urlPart](pageSize);
38
+ if (generatorResult) {
39
+ const filteredData = filterObjects(generatorResult.managedObjects, _requestDescriptor);
40
+
41
+ const currentPage = _requestDescriptor.match(/\"currentPage\"\:(\d+)/)
42
+ ? parseInt(_requestDescriptor.match(/\"currentPage\"\:(\d+)/)[1])
43
+ : null;
44
+
45
+ return generateResponse(
46
+ () => ({
47
+ managedObjects: filteredData,
48
+ ...(!!currentPage && currentPage !== 5 && { next: `currentPage=${currentPage + 1}` })
49
+ }),
50
+ {
51
+ totalPages: 30,
52
+ ...(!!pageSize && { pageSize }),
53
+ ...(!!currentPage && { currentPage }),
54
+ ...(!!currentPage && currentPage !== 5 && { next: `currentPage=${currentPage + 1}` })
55
+ }
56
+ );
57
+ }
58
+ }
59
+ }
60
+ return null;
61
+ }
62
+
63
+ private getResponseGenerators() {
64
+ return {
65
+ pageSize: pageSize => ({
66
+ managedObjects: [...[...Array(pageSize || 10)].map(() => generateDevice())]
67
+ })
68
+ };
69
+ }
70
+ }
@@ -24,7 +24,6 @@ import { WidgetResolversModule } from '../widget-resolvers';
24
24
  import { MockModule } from '../__mocks';
25
25
  import { IntroductionModule } from '../provider-configuration';
26
26
  import { TranslationsModule } from '../translations';
27
- import { DashboardTabsModule } from '../dashboard-tabs';
28
27
  import { BreadcrumbsNodeModule } from '../breadcrumbs/breadcrumbs.module';
29
28
  import { AlarmsModule } from '@c8y/ngx-components/alarms';
30
29
 
@@ -61,7 +60,6 @@ import { AlarmsModule } from '@c8y/ngx-components/alarms';
61
60
  }),
62
61
  RedirectToLastRouteModule,
63
62
  MockModule,
64
- DashboardTabsModule,
65
63
  BreadcrumbsNodeModule,
66
64
  AlarmsModule.config({ hybrid: false })
67
65
  ],
@@ -77,18 +77,20 @@ const exampleSchema: object = {
77
77
  export class JSONSchemaExampleComponent {
78
78
  form = new FormGroup({});
79
79
  model = {};
80
- fields: FormlyFieldConfig[] = [
81
- this.jsonschema.toFieldConfig(exampleSchema, {
82
- map(mappedField: FormlyFieldConfig, _mapSource: JSONSchema7) {
83
- return mappedField;
84
- }
85
- })
86
- ];
80
+ fields: FormlyFieldConfig[];
87
81
 
88
82
  constructor(
89
83
  public jsonschema: C8yJSONSchema,
90
84
  private readonly changeDetectorRef: ChangeDetectorRef
91
- ) {}
85
+ ) {
86
+ this.fields = [
87
+ this.jsonschema.toFieldConfig(exampleSchema, {
88
+ map(mappedField: FormlyFieldConfig, _mapSource: JSONSchema7) {
89
+ return mappedField;
90
+ }
91
+ })
92
+ ];
93
+ }
92
94
 
93
95
  ngAfterViewChecked(): void {
94
96
  this.changeDetectorRef.detectChanges();
@@ -66,18 +66,22 @@ export class ServerGridExampleComponent implements GridConfigContextProvider {
66
66
  hover: true
67
67
  };
68
68
 
69
- columns: Column[] = this.service.getColumns();
70
- pagination: Pagination = this.service.getPagination();
69
+ columns: Column[];
70
+ pagination: Pagination;
71
71
  infiniteScroll: LoadMoreMode = 'auto';
72
72
  serverSideDataCallback: any;
73
73
 
74
74
  refresh: EventEmitter<any> = new EventEmitter<any>();
75
75
 
76
76
  selectable = true;
77
- actionControls: ActionControl[] = this.service.getActionControls();
78
- bulkActionControls: BulkActionControl[] = this.service.getBulkActionControls();
77
+ actionControls: ActionControl[];
78
+ bulkActionControls: BulkActionControl[];
79
79
 
80
80
  constructor(private service: ServerGridExampleService) {
81
+ this.columns = this.service.getColumns();
82
+ this.pagination = this.service.getPagination();
83
+ this.actionControls = this.service.getActionControls();
84
+ this.bulkActionControls = this.service.getBulkActionControls();
81
85
  // we're setting up `serverSideDataCallback` to execute a method from this component with bound `this`
82
86
  this.serverSideDataCallback = this.onDataSourceModifier.bind(this);
83
87
  // we're setting up `onRefreshClick` to be executed on refresh event
@@ -1,6 +1,6 @@
1
1
  <!-- The c8y-title component will display the given string (here: "Awesome Tab") in the header as title -->
2
2
  <c8y-title>Awesome tab</c8y-title>
3
- <div class="card">
3
+ <div class="card m-t-24">
4
4
  <div class="card-block">
5
5
  <p>This is the second tab we added with the <code>hookTab</code>.</p>
6
6
  </div>
@@ -0,0 +1,13 @@
1
+ import { Component } from '@angular/core';
2
+ import { HeaderModule } from '@c8y/ngx-components';
3
+
4
+ @Component({
5
+ selector: 'tut-inline1',
6
+ template: `
7
+ <c8y-title>Inline 1 Component </c8y-title>
8
+ <p>Hello from inline tab 1</p>
9
+ `,
10
+ standalone: true,
11
+ imports: [HeaderModule]
12
+ })
13
+ export class InlineOne {}
@@ -0,0 +1,13 @@
1
+ import { Component } from '@angular/core';
2
+ import { HeaderModule } from '@c8y/ngx-components';
3
+
4
+ @Component({
5
+ selector: 'tut-inline2',
6
+ template: `
7
+ <c8y-title>Inline 2 Component </c8y-title>
8
+ <p>Hello from inline tab 2</p>
9
+ `,
10
+ standalone: true,
11
+ imports: [HeaderModule]
12
+ })
13
+ export class InlineTwo {}
@@ -0,0 +1,26 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { RouterModule, Routes } from '@angular/router';
4
+ import { InlineTwo } from './inline-two.component';
5
+ import { InlineOne } from './inline-one.component';
6
+
7
+ const routes: Routes = [
8
+ {
9
+ path: '',
10
+ redirectTo: 'inline1',
11
+ pathMatch: 'full'
12
+ },
13
+ {
14
+ path: 'inline1',
15
+ component: InlineOne
16
+ },
17
+ {
18
+ path: 'inline2',
19
+ component: InlineTwo
20
+ }
21
+ ];
22
+
23
+ @NgModule({
24
+ imports: [CommonModule, RouterModule.forChild(routes)]
25
+ })
26
+ export class InlineModule {}
@@ -1,6 +1,6 @@
1
1
  <!-- The c8y-title component will display the given string (here: "Outstanding Tab") in the header as title -->
2
2
  <c8y-title>Outstanding tab</c8y-title>
3
- <div class="card">
3
+ <div class="card m-t-24">
4
4
  <div class="card-block">
5
5
  <p>
6
6
  This is the first tab we added with the
@@ -13,10 +13,21 @@
13
13
  toggles the orientation for the whole application:
14
14
  </p>
15
15
  <button
16
- class="btn btn-primary"
16
+ class="btn btn-primary m-t-16"
17
17
  (click)="toggleOrientation()"
18
18
  >
19
19
  Toggle orientation
20
20
  </button>
21
21
  </div>
22
22
  </div>
23
+ <div class="card">
24
+ <div class="p-relative">
25
+ <c8y-tabs-outlet
26
+ orientation="horizontal"
27
+ outletName="inline-example"
28
+ ></c8y-tabs-outlet>
29
+ </div>
30
+ <div class="p-16" style="min-height: 100px">
31
+ <router-outlet></router-outlet>
32
+ </div>
33
+ </div>
@@ -1,4 +1,5 @@
1
1
  import { Component } from '@angular/core';
2
+ import { RouterModule } from '@angular/router';
2
3
  import { CoreModule, OptionsService, TabsService } from '@c8y/ngx-components';
3
4
 
4
5
  /**
@@ -12,7 +13,7 @@ import { CoreModule, OptionsService, TabsService } from '@c8y/ngx-components';
12
13
  selector: 'outstanding',
13
14
  templateUrl: './outstanding.component.html',
14
15
  standalone: true,
15
- imports: [CoreModule]
16
+ imports: [CoreModule, RouterModule]
16
17
  })
17
18
  export class OutstandingComponent {
18
19
  constructor(
@@ -7,8 +7,7 @@ export class ExampleTabFactory implements TabFactory {
7
7
  // Inject the angular Router
8
8
  constructor(public router: Router) {}
9
9
 
10
- // Implement the get()-method, otherwise the ExampleTabFactory
11
- // implements the TabFactory interface incorrectly (!)
10
+ // Implement the get()-method which is called to receive the tabs on each navigation
12
11
  get() {
13
12
  const tabs: Tab[] = [];
14
13
  /**
@@ -16,13 +15,12 @@ export class ExampleTabFactory implements TabFactory {
16
15
  * - Awesome
17
16
  * - Outstanding
18
17
  * but these tabs should only displayed if the URL matches
19
- * something like: .../apps/tutorial-application/#/world/
20
18
  */
21
19
  if (this.router.url.match(/\/tabs/g)) {
22
20
  /**
23
21
  * mandatory for a Tab is the path (string) and the label (string)
24
22
  * A click on the tab will load the given path and therefore angular loads the
25
- * specified component (check: ../app.modules.ts)
23
+ * specified component.
26
24
  */
27
25
  tabs.push({
28
26
  path: 'hooks/tabs/awesome',
@@ -39,6 +37,24 @@ export class ExampleTabFactory implements TabFactory {
39
37
  } as Tab);
40
38
  }
41
39
 
40
+ // We also define two more tabs for the "inline" tabs which
41
+ // are rendered into any <c8y-tabs-outlet outletName="inline-example"> component
42
+ tabs.push({
43
+ path: 'inline1',
44
+ priority: 1000,
45
+ label: 'Inline 1',
46
+ icon: 'diamond',
47
+ tabsOutlet: 'inline-example'
48
+ } as Tab);
49
+
50
+ tabs.push({
51
+ path: 'inline2',
52
+ priority: 1000,
53
+ label: 'Inline 2',
54
+ icon: 'diamond',
55
+ tabsOutlet: 'inline-example'
56
+ } as Tab);
57
+
42
58
  return tabs;
43
59
  }
44
60
  }
@@ -3,20 +3,25 @@ import { NavigatorNode, hookNavigator, hookRoute, hookTab } from '@c8y/ngx-compo
3
3
  import { ExampleTabFactory } from './tab';
4
4
 
5
5
  export const hooks = [
6
+ // important
6
7
  hookTab(ExampleTabFactory),
7
- hookRoute({
8
- path: 'hooks/tabs',
9
- redirectTo: 'hooks/tabs/outstanding'
10
- }),
11
- hookRoute({
12
- path: 'hooks/tabs/outstanding',
13
- loadComponent: () =>
14
- import('./outstanding/outstanding.component').then(m => m.OutstandingComponent)
15
- }),
16
- hookRoute({
17
- path: 'hooks/tabs/awesome',
18
- loadComponent: () => import('./awesome/awesome.component').then(m => m.AwesomeComponent)
19
- }),
8
+ // /important
9
+ hookRoute([
10
+ {
11
+ path: 'hooks/tabs',
12
+ redirectTo: 'hooks/tabs/outstanding'
13
+ },
14
+ {
15
+ path: 'hooks/tabs/outstanding',
16
+ loadComponent: () =>
17
+ import('./outstanding/outstanding.component').then(m => m.OutstandingComponent),
18
+ loadChildren: () => import('./inline/inline.module').then(m => m.InlineModule)
19
+ },
20
+ {
21
+ path: 'hooks/tabs/awesome',
22
+ loadComponent: () => import('./awesome/awesome.component').then(m => m.AwesomeComponent)
23
+ }
24
+ ]),
20
25
  hookNavigator(
21
26
  new NavigatorNode({
22
27
  priority: 50,
package/src/i18n.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import '@c8y/ngx-components/locales/de.po';
7
7
  import '@c8y/ngx-components/locales/en.po';
8
+ import '@c8y/ngx-components/locales/en_US.po';
8
9
  import '@c8y/ngx-components/locales/es.po';
9
10
  import '@c8y/ngx-components/locales/fr.po';
10
11
  import '@c8y/ngx-components/locales/ja_JP.po';
@@ -12,7 +13,6 @@ import '@c8y/ngx-components/locales/ko.po';
12
13
  import '@c8y/ngx-components/locales/nl.po';
13
14
  import '@c8y/ngx-components/locales/pl.po';
14
15
  import '@c8y/ngx-components/locales/pt_BR.po';
15
- import '@c8y/ngx-components/locales/ru.po';
16
16
  import '@c8y/ngx-components/locales/zh_CN.po';
17
17
  import '@c8y/ngx-components/locales/zh_TW.po';
18
18
  // import './locales/de.po'; // <- adding additional strings to the german translation.
package/src/main.ts CHANGED
@@ -1,17 +1,13 @@
1
1
  import './i18n';
2
2
  import { applyOptions, loadOptions } from '@c8y/bootstrap';
3
3
 
4
- /** Verify that custom webpack config is working */
5
- declare const HELLO_WORLD: string;
6
- console.log(`${HELLO_WORLD} from custom webpack config`);
7
-
8
- const barHolder: HTMLElement = document.querySelector('body > .init-load');
9
- export const removeProgress = () => barHolder && barHolder.parentNode.removeChild(barHolder);
4
+ const barHolder: HTMLElement | null = document.querySelector('body > .init-load');
5
+ export const removeProgress = () => barHolder?.parentNode?.removeChild(barHolder);
10
6
 
11
7
  applicationSetup();
12
8
 
13
9
  async function applicationSetup() {
14
- const options = await applyOptions({
10
+ await applyOptions({
15
11
  ...(await loadOptions())
16
12
  });
17
13
 
@@ -19,7 +15,6 @@ async function applicationSetup() {
19
15
  /* webpackPreload: true */
20
16
  './bootstrap'
21
17
  );
22
- const bootstrapApp = mod.bootstrap || (window as any).bootstrap || (() => null);
23
-
24
- return Promise.resolve(bootstrapApp(options)).then(removeProgress);
18
+ const bootstrapApp = mod.bootstrap;
19
+ return bootstrapApp().then(removeProgress);
25
20
  }
@@ -1,8 +1,11 @@
1
1
  import { Component, Input } from '@angular/core';
2
2
  import { FormBuilder, FormGroup } from '@angular/forms';
3
3
  import { CommonModule, CoreModule } from '@c8y/ngx-components';
4
- import { AlarmEventSelectorModule, AlarmOrEvent } from '@c8y/ngx-components/alarm-event-selector';
5
- import { AlarmEventSelectorModalOptions } from '@c8y/ngx-components/alarm-event-selector/alarm-event-selector-modal/alarm-event-selector-modal.model';
4
+ import {
5
+ AlarmEventSelectorModule,
6
+ AlarmOrEvent,
7
+ AlarmEventSelectorModalOptions
8
+ } from '@c8y/ngx-components/alarm-event-selector';
6
9
  import { AssetSelectorModule } from '@c8y/ngx-components/assets-navigator';
7
10
 
8
11
  @Component({
@@ -2,9 +2,9 @@ import { Component, OnInit } from '@angular/core';
2
2
  import { IManagedObject, InventoryService } from '@c8y/client';
3
3
  import {
4
4
  DatapointSelectorModule,
5
- DatapointSelectorService
5
+ DatapointSelectorService,
6
+ KPIDetails
6
7
  } from '@c8y/ngx-components/datapoint-selector';
7
- import { KPIDetails } from '@c8y/ngx-components/datapoint-selector/datapoint-selection.model';
8
8
  import { CommonModule } from '@angular/common';
9
9
  import { CoreModule } from '@c8y/ngx-components';
10
10
  import { AssetSelectorModule } from '@c8y/ngx-components/assets-navigator';
@@ -0,0 +1,45 @@
1
+ <c8y-title>Typeahead</c8y-title>
2
+
3
+ <div class="row">
4
+ <div class="col-xs-6">
5
+ <c8y-typeahead
6
+ container="body"
7
+ name="selectedDevice"
8
+ [placeholder]="'Search for devices...'"
9
+ (onSearch)="setPipe($event)"
10
+ [allowFreeEntries]="true"
11
+ [(ngModel)]="selectedDevice"
12
+ >
13
+ <c8y-li
14
+ class="p-l-8 p-r-8 c8y-list__item--link"
15
+ *c8yFor="let device of devices; notFound: notFoundTemplate; pipe: filterPipe"
16
+ (click)="selectedDevice = device"
17
+ [active]="selectedDevice === device"
18
+ >
19
+ <c8y-highlight
20
+ [text]="device.name"
21
+ [pattern]="pattern"
22
+ ></c8y-highlight>
23
+ </c8y-li>
24
+ <ng-template #notFoundTemplate>
25
+ <c8y-li
26
+ class="bg-level-2 p-8 sticky-bottom"
27
+ *ngIf="pattern.length > 0"
28
+ >
29
+ <span translate>No exact match found.</span>
30
+ <button
31
+ class="btn btn-default btn-sm m-l-8"
32
+ title="Add new device"
33
+ type="button"
34
+ translate
35
+ >
36
+ Add new device
37
+ </button>
38
+ </c8y-li>
39
+ </ng-template>
40
+ </c8y-typeahead>
41
+ </div>
42
+ <div class="col-xs-6">
43
+ <pre>{{ selectedDevice | json }}</pre>
44
+ </div>
45
+ </div>
@@ -0,0 +1,49 @@
1
+ import { Component } from '@angular/core';
2
+ import { CoreModule, ForOfFilterPipe } from '@c8y/ngx-components';
3
+ import { IManagedObject, InventoryService, IResultList } from '@c8y/client';
4
+ import { pipe } from 'rxjs';
5
+ import { map, tap } from 'rxjs/operators';
6
+
7
+ @Component({
8
+ selector: 'tut-typeahead-example',
9
+ templateUrl: './typeahead-example.component.html',
10
+ standalone: true,
11
+ imports: [CoreModule]
12
+ })
13
+ export class TypeaheadExampleComponent {
14
+ devices: IResultList<IManagedObject>;
15
+ filterPipe: ForOfFilterPipe = pipe(tap());
16
+ pattern = '';
17
+ selectedDevice: IManagedObject;
18
+
19
+ constructor(private inventoryService: InventoryService) {}
20
+
21
+ ngOnInit(): void {
22
+ this.loadDevices();
23
+ }
24
+
25
+ async loadDevices() {
26
+ this.devices = await this.inventoryService.list({
27
+ pageSize: 10,
28
+ withTotalPages: true,
29
+ fragmentType: 'c8y_IsDevice',
30
+ currentPage: 1
31
+ });
32
+ }
33
+
34
+ async reload() {
35
+ await this.loadDevices();
36
+ }
37
+
38
+ setPipe(filterStr: string) {
39
+ this.pattern = filterStr;
40
+ this.filterPipe = pipe(
41
+ map((data: []) => {
42
+ return data.filter(
43
+ (mo: IManagedObject) =>
44
+ mo.name && mo.name.toLowerCase().indexOf(filterStr.toLowerCase()) > -1
45
+ );
46
+ })
47
+ );
48
+ }
49
+ }
@@ -0,0 +1,19 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { hookNavigator, hookRoute, NavigatorNode } from '@c8y/ngx-components';
3
+
4
+ @NgModule({
5
+ providers: [
6
+ hookRoute({
7
+ path: 'typeahead',
8
+ loadComponent: () =>
9
+ import('./typeahead-example.component').then(m => m.TypeaheadExampleComponent)
10
+ }),
11
+ hookNavigator(
12
+ new NavigatorNode({
13
+ label: 'Typeahead',
14
+ path: 'typeahead'
15
+ })
16
+ )
17
+ ]
18
+ })
19
+ export class TypeaheadExampleModule {}
@@ -1,95 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { CoreModule, Tab, TabsService } from '@c8y/ngx-components';
3
- import { Observable } from 'rxjs';
4
-
5
- @Component({
6
- selector: 'component1',
7
- template: 'component1',
8
- standalone: true
9
- })
10
- export class Component1 {
11
- ngOnInit() {
12
- console.log('Component 1 initialized');
13
- }
14
- }
15
- @Component({
16
- selector: 'component2',
17
- template: 'component2',
18
- standalone: true
19
- })
20
- export class Component2 {
21
- ngOnInit() {
22
- console.log('Component 2 initialized');
23
- }
24
- }
25
- @Component({
26
- selector: 'component3',
27
- template: 'component3',
28
- standalone: true
29
- })
30
- export class Component3 {
31
- ngOnInit() {
32
- console.log('Component 3 initialized');
33
- }
34
- }
35
-
36
- @Component({
37
- selector: 'app-dashboard-tabs',
38
- template: `<div>
39
- <c8y-title>Dashboard Tabs</c8y-title>
40
- <h1>Inline Tabs</h1>
41
- <div>
42
- <c8y-tabs-outlet
43
- [tabs]="tabs$ | async"
44
- [outletName]="'dashboardTabs'"
45
- [orientation]="'vertical'"
46
- >
47
- </c8y-tabs-outlet>
48
- <c8y-tab
49
- [label]="'Tab1'"
50
- [tabsOutlet]="'dashboardTabs'"
51
- (onSelect)="selectTab('Tab1')"
52
- [isActive]="selectedTab === 'Tab1'"
53
- >
54
- </c8y-tab>
55
- <c8y-tab
56
- [label]="'Tab2'"
57
- [tabsOutlet]="'dashboardTabs'"
58
- (onSelect)="selectTab('Tab2')"
59
- [isActive]="selectedTab === 'Tab2'"
60
- >
61
- </c8y-tab>
62
- <c8y-tab
63
- [label]="'Tab3'"
64
- [tabsOutlet]="'dashboardTabs'"
65
- (onSelect)="selectTab('Tab3')"
66
- [isActive]="selectedTab === 'Tab3'"
67
- >
68
- </c8y-tab>
69
-
70
- <ng-container [ngSwitch]="selectedTab">
71
- <component1 *ngSwitchCase="'Tab1'"></component1>
72
- <component2 *ngSwitchCase="'Tab2'"></component2>
73
- <component3 *ngSwitchCase="'Tab3'"></component3>
74
- </ng-container>
75
- </div>
76
- </div>`,
77
- standalone: true,
78
- imports: [CoreModule, Component1, Component2, Component3]
79
- })
80
- export class DashboardTabsComponent {
81
- tabs$: Observable<Tab[]>;
82
- selectedTab: string;
83
-
84
- constructor(private tabsService: TabsService) {}
85
-
86
- ngOnInit() {
87
- this.tabs$ = this.tabsService.items$;
88
- }
89
-
90
- selectTab(selectedTab: string) {
91
- this.selectedTab = selectedTab;
92
- console.log(this.selectedTab);
93
- this.tabsService.refresh();
94
- }
95
- }
@@ -1,20 +0,0 @@
1
- import { NgModule } from '@angular/core';
2
- import { hookNavigator, hookRoute, NavigatorNode } from '@c8y/ngx-components';
3
-
4
- @NgModule({
5
- providers: [
6
- hookRoute({
7
- path: 'dashboard-tabs/dashboardTabs',
8
- loadComponent: () => import('./dashboard-tabs.component').then(m => m.DashboardTabsComponent)
9
- }),
10
- hookNavigator(
11
- new NavigatorNode({
12
- path: 'dashboard-tabs/dashboardTabs',
13
- label: 'Dashboard Tabs',
14
- icon: 'rocket',
15
- priority: 1000
16
- })
17
- )
18
- ]
19
- })
20
- export class DashboardTabsModule {}
@@ -1 +0,0 @@
1
- export * from './dashboard-tabs.module';
package/src/favicon.ico DELETED
Binary file