@c8y/tutorial 1022.10.1 → 1022.16.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.
- package/cumulocity.config.ts +39 -4
- package/package.json +7 -7
- package/src/__mocks/global-mocks/inventory.interceptor.ts +6 -1
- package/src/__mocks/global-mocks/provider-configuration.ts +62 -0
- package/src/__mocks/global-mocks/provider-definitions.ts +24 -0
- package/src/__mocks/index.ts +18 -0
- package/src/countdown/countdown-example.component.html +4 -1
- package/src/countdown/countdown-example.component.ts +1 -0
- package/src/dynamic-forms/custom-element-example/custom-element-example.component.ts +2 -2
- package/src/dynamic-forms/introduction-example/introduction-example.component.ts +2 -2
- package/src/dynamic-forms/json-schema-example/json-schema-example.component.html +2 -2
- package/src/dynamic-forms/validation-example/validation-example.component.ts +2 -2
- package/src/for-of-directive/for-of-example.component.ts +3 -3
- package/src/generate-json-schema/generate-json-schema.component.ts +1 -0
- package/src/hooks/docs/docs-example.service.ts +17 -0
- package/src/hooks/docs/hook-docs-example.component.ts +17 -0
- package/src/hooks/docs/hook-docs.module.ts +30 -0
- package/src/hooks/preview-feature/index.ts +0 -1
- package/src/hooks/tabs/named-outlet/basic-view/basic-view.component.html +15 -0
- package/src/hooks/tabs/named-outlet/basic-view/basic-view.component.ts +25 -0
- package/src/hooks/tabs/named-outlet/content-a.component.ts +8 -0
- package/src/hooks/tabs/named-outlet/content-b.component.ts +8 -0
- package/src/hooks/tabs/named-outlet/named-outlet.module.ts +80 -0
- package/src/hooks/tabs/tabs.module.ts +0 -2
- package/src/hooks/widget/context-dashboard.component.ts +13 -0
- package/src/hooks/widget/widget.providers.ts +18 -0
- package/src/hooks/widget-config/basic-view/basic-edit.component.ts +18 -1
- package/src/hooks/widget-config/widget-config.providers.ts +0 -3
- package/src/input-group/extendable-input-list-example.component.ts +19 -3
- package/src/lazy-widget/lazy-widget-config/lazy-widget-config.component.ts +19 -3
- package/src/list/list/list-check/list-check.component.html +1 -1
- package/src/maps/cluster-map/cluster-map-example.component.html +31 -10
- package/src/maps/cluster-map/cluster-map-example.component.ts +7 -2
- package/src/maps/cluster-map-root-node/cluster-map-root-node-example.component.html +13 -17
- package/src/maps/map-popup/map-popup-example.component.html +4 -4
- package/src/maps/simple-map/simple-map-example.component.html +8 -5
- package/src/maps/simple-map/simple-map-example.module.ts +1 -1
- package/src/maps/simple-map-custom-config/map-layer.service.ts +50 -0
- package/src/maps/simple-map-custom-config/simple-map-custom-config.component.html +27 -0
- package/src/maps/simple-map-custom-config/simple-map-custom-config.component.ts +16 -0
- package/src/maps/simple-map-custom-config/simple-map-custom-config.module.ts +35 -0
- package/src/pattern-messages/pattern-messages-array.ts +20 -0
- package/src/pattern-messages/pattern-messages-factory.ts +18 -0
- package/src/pattern-messages/pattern-messages-single.ts +10 -0
- package/src/popconfirm/pop-confirm-example.component.ts +5 -2
- package/src/quick-link/quick-link-example.component.ts +0 -3
- package/src/realtime/realtime-tutorial.component.html +39 -30
- package/src/selector/alarm-event-selector-example/alarm-event-selector.component.ts +19 -15
- package/src/selector/data-points-export-selector-example/datapoints-export-selector.component.ts +11 -15
- package/src/translations/text-translation/gettext-translation/text-translation-gettext.component.ts +8 -6
- package/src/hooks/preview-feature/preview-feature.module.ts +0 -11
- package/src/hooks/widget-config/basic-view/basic-edit.component.html +0 -18
|
@@ -36,7 +36,6 @@ export const widgetConfigHookProviders = [
|
|
|
36
36
|
})
|
|
37
37
|
),
|
|
38
38
|
hookComponent(referenceWidgetDefinition),
|
|
39
|
-
// important
|
|
40
39
|
hookWidgetConfig({
|
|
41
40
|
widgetId: 'reference.component',
|
|
42
41
|
label: 'An additional Configuration for the simple component',
|
|
@@ -47,7 +46,6 @@ export const widgetConfigHookProviders = [
|
|
|
47
46
|
m => m.AdditionalConfigComponent
|
|
48
47
|
)
|
|
49
48
|
}),
|
|
50
|
-
|
|
51
49
|
hookWidgetConfig({
|
|
52
50
|
widgetId: 'reference.component',
|
|
53
51
|
label: 'The default asset selector.',
|
|
@@ -55,5 +53,4 @@ export const widgetConfigHookProviders = [
|
|
|
55
53
|
loadComponent: () =>
|
|
56
54
|
import('@c8y/ngx-components/context-dashboard').then(m => m.WidgetAssetSelectorComponent)
|
|
57
55
|
})
|
|
58
|
-
// /important
|
|
59
56
|
];
|
|
@@ -9,15 +9,20 @@ import { CoreModule, FormsModule } from '@c8y/ngx-components';
|
|
|
9
9
|
<ul class="list-unstyled p-t-16" c8yInputGroupListContainer>
|
|
10
10
|
<li class="m-b-8" *ngFor="let item of items; let i = index; trackBy: trackByFn">
|
|
11
11
|
<c8y-input-group-list
|
|
12
|
+
[attr.aria-label]="'Input group-' + (i + 1)"
|
|
12
13
|
[index]="i"
|
|
13
|
-
(onAdd)="add()"
|
|
14
|
-
(onRemove)="remove(
|
|
14
|
+
(onAdd)="add(); announceChange('Item added')"
|
|
15
|
+
(onRemove)="remove(i); announceChange('Item removed')"
|
|
15
16
|
[minus]="items.length > 1"
|
|
16
17
|
>
|
|
17
18
|
<c8y-form-group class="form-group--tooltip-validation">
|
|
19
|
+
<label class="sr-only" [attr.for]="'extendable-input-' + i"
|
|
20
|
+
>List item {{ i + 1 }}</label
|
|
21
|
+
>
|
|
18
22
|
<input
|
|
19
23
|
class="form-control"
|
|
20
|
-
|
|
24
|
+
[attr.aria-label]="'List item-' + (i + 1)"
|
|
25
|
+
placeholder="e.g. placeholder"
|
|
21
26
|
type="text"
|
|
22
27
|
[required]="true"
|
|
23
28
|
[(ngModel)]="items[i]"
|
|
@@ -26,12 +31,15 @@ import { CoreModule, FormsModule } from '@c8y/ngx-components';
|
|
|
26
31
|
</c8y-input-group-list>
|
|
27
32
|
</li>
|
|
28
33
|
</ul>
|
|
34
|
+
<!-- aria-live region for screen reader announcements -->
|
|
35
|
+
<div class="sr-only" aria-live="polite" #liveRegion>{{ liveMessage }}</div>
|
|
29
36
|
</div>`,
|
|
30
37
|
standalone: true,
|
|
31
38
|
imports: [CoreModule, FormsModule, CommonModule]
|
|
32
39
|
})
|
|
33
40
|
export class ExtendableInputListExampleComponent {
|
|
34
41
|
items: string[] = [];
|
|
42
|
+
liveMessage = '';
|
|
35
43
|
|
|
36
44
|
ngOnInit() {
|
|
37
45
|
this.add();
|
|
@@ -48,4 +56,12 @@ export class ExtendableInputListExampleComponent {
|
|
|
48
56
|
remove(index) {
|
|
49
57
|
this.items.splice(index, 1);
|
|
50
58
|
}
|
|
59
|
+
|
|
60
|
+
announceChange(message: string) {
|
|
61
|
+
this.liveMessage = message;
|
|
62
|
+
// Optionally clear the message after a short delay for repeated announcements
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
this.liveMessage = '';
|
|
65
|
+
}, 1000);
|
|
66
|
+
}
|
|
51
67
|
}
|
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
import { Component, Input } from '@angular/core';
|
|
1
|
+
import { Component, Input, TemplateRef, ViewChild } from '@angular/core';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { WidgetConfigService } from '@c8y/ngx-components/context-dashboard';
|
|
3
4
|
import { WidgetConfig } from '../widget-config.model';
|
|
5
|
+
import { LazyWidgetViewComponent } from '../lazy-widget-view';
|
|
4
6
|
|
|
5
7
|
@Component({
|
|
6
8
|
selector: 'tutorial-lazy-widget-config',
|
|
7
|
-
template: `<p>This widget's configuration component/module is only loaded when needed.</p
|
|
9
|
+
template: `<p>This widget's configuration component/module is only loaded when needed.</p>
|
|
10
|
+
<ng-template #lazyWidgetPreview>
|
|
11
|
+
<tutorial-lazy-widget-view></tutorial-lazy-widget-view>
|
|
12
|
+
</ng-template>`,
|
|
8
13
|
standalone: true,
|
|
9
|
-
imports: [CommonModule]
|
|
14
|
+
imports: [CommonModule, LazyWidgetViewComponent]
|
|
10
15
|
})
|
|
11
16
|
export class LazyWidgetConfigComponent {
|
|
12
17
|
@Input() config: WidgetConfig;
|
|
18
|
+
|
|
19
|
+
@ViewChild('lazyWidgetPreview', { static: true })
|
|
20
|
+
set previewMapSet(template: TemplateRef<any>) {
|
|
21
|
+
if (template) {
|
|
22
|
+
this.widgetConfigService.setPreview(template);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
this.widgetConfigService.setPreview(null);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
constructor(private widgetConfigService: WidgetConfigService) {}
|
|
13
29
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<c8y-title>Cluster map example</c8y-title>
|
|
2
|
-
<div class="d-flex
|
|
3
|
-
<div class="d-flex d-col j-c-center p-16">
|
|
2
|
+
<div class="d-flex">
|
|
3
|
+
<div class="d-flex d-col j-c-center p-r-16" style="width: 280px;">
|
|
4
4
|
<button
|
|
5
5
|
class="btn btn-default btn-block"
|
|
6
6
|
(click)="setRandomZoomLevel()"
|
|
@@ -9,9 +9,23 @@
|
|
|
9
9
|
</button>
|
|
10
10
|
<button
|
|
11
11
|
class="btn btn-default btn-block"
|
|
12
|
-
(click)="
|
|
12
|
+
(click)="setCenterNY()"
|
|
13
|
+
*ngIf="40.7128 !== config.center[0] || -74.006 !== config.center[1]"
|
|
13
14
|
>
|
|
14
|
-
|
|
15
|
+
Change center to New York
|
|
16
|
+
</button>
|
|
17
|
+
<button
|
|
18
|
+
class="btn btn-default btn-block"
|
|
19
|
+
(click)="setCenterDus()"
|
|
20
|
+
*ngIf="51.23544 !== config.center[0] || 6.79599 !== config.center[1]"
|
|
21
|
+
>
|
|
22
|
+
Change center to Düsseldorf
|
|
23
|
+
</button>
|
|
24
|
+
<button
|
|
25
|
+
class="btn btn-default btn-block"
|
|
26
|
+
(click)="map.center()"
|
|
27
|
+
>
|
|
28
|
+
Go back to defined center
|
|
15
29
|
</button>
|
|
16
30
|
<button
|
|
17
31
|
class="btn btn-default btn-block"
|
|
@@ -37,12 +51,19 @@
|
|
|
37
51
|
>
|
|
38
52
|
Show cluster color
|
|
39
53
|
</button>
|
|
54
|
+
<button
|
|
55
|
+
class="btn btn-default btn-block"
|
|
56
|
+
(click)="showMapStatus = !showMapStatus"
|
|
57
|
+
>
|
|
58
|
+
Show map status
|
|
59
|
+
</button>
|
|
40
60
|
</div>
|
|
41
61
|
<!-- important -->
|
|
42
|
-
<div
|
|
62
|
+
<div class="flex-grow p-relative a-s-stretch">
|
|
43
63
|
<c8y-map-status
|
|
44
64
|
[clusterMap]="map"
|
|
45
65
|
[(config)]="config"
|
|
66
|
+
*ngIf="showMapStatus"
|
|
46
67
|
></c8y-map-status>
|
|
47
68
|
<c8y-cluster-map
|
|
48
69
|
#map
|
|
@@ -51,10 +72,10 @@
|
|
|
51
72
|
></c8y-cluster-map>
|
|
52
73
|
</div>
|
|
53
74
|
<!-- /important -->
|
|
54
|
-
<
|
|
55
|
-
class="a-s-stretch p-16"
|
|
56
|
-
style="width:
|
|
75
|
+
<div
|
|
76
|
+
class="a-s-stretch p-16 d-col bg-info-light"
|
|
77
|
+
style="width: 320px; height: 420px;"
|
|
57
78
|
>
|
|
58
|
-
<pre>{{ config | json }} </pre>
|
|
59
|
-
</
|
|
79
|
+
<pre class="flex-grow">{{ config | json }} </pre>
|
|
80
|
+
</div>
|
|
60
81
|
</div>
|
|
@@ -13,13 +13,18 @@ import { AssetSelectorModule } from '@c8y/ngx-components/assets-navigator';
|
|
|
13
13
|
export class ClusterMapExampleComponent {
|
|
14
14
|
config: ClusterMapConfig = { center: defaultMapConfig.center, zoomLevel: 4 };
|
|
15
15
|
showClusterColor = false;
|
|
16
|
+
showMapStatus = true;
|
|
16
17
|
|
|
17
18
|
setRandomZoomLevel() {
|
|
18
19
|
this.config = { ...this.config, zoomLevel: Math.floor(1 + Math.random() * 11) };
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
this.config = { ...this.config, center:
|
|
22
|
+
setCenterNY() {
|
|
23
|
+
this.config = { ...this.config, center: [40.7128, -74.006] };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setCenterDus() {
|
|
27
|
+
this.config = { ...this.config, center: [51.23544, 6.79599] };
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
changeIcon() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<c8y-title>Cluster map with root node</c8y-title>
|
|
2
2
|
|
|
3
|
-
<div class="d-flex
|
|
4
|
-
<div class="d-flex d-col
|
|
3
|
+
<div class="d-flex">
|
|
4
|
+
<div class="d-flex d-col" style="width: 280px;">
|
|
5
5
|
<c8y-asset-selector
|
|
6
6
|
[(ngModel)]="rootNode"
|
|
7
7
|
[config]="{
|
|
@@ -9,10 +9,12 @@
|
|
|
9
9
|
groupsOnly: false
|
|
10
10
|
}"
|
|
11
11
|
(change)="resetConfig()"
|
|
12
|
+
class="bg-level-1 min-height-0"
|
|
13
|
+
style="height: 420px;"
|
|
12
14
|
></c8y-asset-selector>
|
|
13
15
|
</div>
|
|
14
16
|
<!-- important -->
|
|
15
|
-
<div
|
|
17
|
+
<div class="flex-grow p-relative a-s-stretch">
|
|
16
18
|
<c8y-map-status
|
|
17
19
|
[clusterMap]="map"
|
|
18
20
|
[(config)]="followConfig"
|
|
@@ -36,19 +38,13 @@
|
|
|
36
38
|
</c8y-cluster-map>
|
|
37
39
|
</div>
|
|
38
40
|
<!-- /important -->
|
|
39
|
-
<
|
|
40
|
-
class="a-s-stretch p-16"
|
|
41
|
-
style="width:
|
|
41
|
+
<div
|
|
42
|
+
class="a-s-stretch p-16 d-col bg-info-light"
|
|
43
|
+
style="width: 320px; height: 420px;"
|
|
42
44
|
>
|
|
43
|
-
RootNode
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
</
|
|
47
|
-
|
|
48
|
-
<br />
|
|
49
|
-
Config:
|
|
50
|
-
<code>
|
|
51
|
-
<pre style="max-height: 120px">{{ followConfig | json }} </pre>
|
|
52
|
-
</code>
|
|
53
|
-
</code>
|
|
45
|
+
<label>RootNode</label>
|
|
46
|
+
<pre style="height: 120px">{{ rootNode | json }} </pre>
|
|
47
|
+
<label>Config</label>
|
|
48
|
+
<pre class="flex-grow">{{ followConfig | json }} </pre>
|
|
49
|
+
</div>
|
|
54
50
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<c8y-title>Map with popup example</c8y-title>
|
|
2
2
|
|
|
3
|
-
<div class="d-flex
|
|
4
|
-
<div class="d-flex d-col j-c-center p-16">
|
|
3
|
+
<div class="d-flex">
|
|
4
|
+
<div class="d-flex d-col j-c-center p-r-16" style="width: 280px; height: 420px;">
|
|
5
5
|
<button
|
|
6
6
|
class="btn btn-primary btn-block"
|
|
7
7
|
(click)="showFirstPopup()"
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
</button>
|
|
17
17
|
</div>
|
|
18
18
|
<!-- important -->
|
|
19
|
-
<div
|
|
19
|
+
<div class="flex-grow p-relative a-s-stretch">
|
|
20
20
|
<c8y-map
|
|
21
21
|
[assets]="exampleDevices"
|
|
22
22
|
[config]="config"
|
|
23
23
|
>
|
|
24
24
|
<div *c8yMapPopup="let context">
|
|
25
|
-
Hello World from
|
|
25
|
+
<b>Hello World from:</b>
|
|
26
26
|
<br />
|
|
27
27
|
name: {{ context.name }}
|
|
28
28
|
<br />
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<c8y-title>Simple map example</c8y-title>
|
|
2
2
|
|
|
3
|
-
<div class="d-flex
|
|
4
|
-
<div class="d-flex d-col j-c-center p-16">
|
|
3
|
+
<div class="d-flex">
|
|
4
|
+
<div class="d-flex d-col j-c-center p-r-16" style="width: 280px;">
|
|
5
5
|
<button
|
|
6
6
|
class="btn btn-default btn-block"
|
|
7
7
|
(click)="changeDevices()"
|
|
@@ -46,14 +46,17 @@
|
|
|
46
46
|
</button>
|
|
47
47
|
</div>
|
|
48
48
|
<!-- important -->
|
|
49
|
-
<div
|
|
49
|
+
<div class="flex-grow p-relative a-s-stretch">
|
|
50
50
|
<c8y-map
|
|
51
51
|
[assets]="exampleDevices"
|
|
52
52
|
[config]="config"
|
|
53
53
|
></c8y-map>
|
|
54
54
|
</div>
|
|
55
55
|
<!-- /important -->
|
|
56
|
-
<
|
|
56
|
+
<div
|
|
57
|
+
class="a-s-stretch p-16 d-col bg-info-light"
|
|
58
|
+
style="width: 320px; height: 420px;"
|
|
59
|
+
>
|
|
57
60
|
<pre>{{ config | json }} </pre>
|
|
58
|
-
</
|
|
61
|
+
</div>
|
|
59
62
|
</div>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { defaultLayer } from '@c8y/ngx-components/map';
|
|
3
|
+
import { MapTileLayer } from '@c8y/options';
|
|
4
|
+
import { BehaviorSubject, Observable } from 'rxjs';
|
|
5
|
+
|
|
6
|
+
@Injectable({
|
|
7
|
+
providedIn: 'root'
|
|
8
|
+
})
|
|
9
|
+
export class MapLayerService implements CumulocityServiceRegistry.MapTileLayerProvider {
|
|
10
|
+
maps$ = new BehaviorSubject<MapTileLayer[]>([defaultLayer]);
|
|
11
|
+
|
|
12
|
+
getMapTileLayers$(): Observable<MapTileLayer[]> {
|
|
13
|
+
return this.maps$;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
overridesDefaultLayer(): boolean {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
changeLayer(name: 'Carto' | 'OpenTopo') {
|
|
21
|
+
if (name === 'Carto') {
|
|
22
|
+
this.maps$.next([
|
|
23
|
+
{
|
|
24
|
+
layerUrl: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png',
|
|
25
|
+
label: 'Carto',
|
|
26
|
+
priority: 1000,
|
|
27
|
+
options: {
|
|
28
|
+
maxZoom: 12
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]);
|
|
32
|
+
} else if (name === 'OpenTopo') {
|
|
33
|
+
this.maps$.next([
|
|
34
|
+
{
|
|
35
|
+
layerUrl: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
|
|
36
|
+
label: 'OpenTopo',
|
|
37
|
+
priority: 1000,
|
|
38
|
+
options: {
|
|
39
|
+
maxZoom: 17,
|
|
40
|
+
minZoom: 0
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
revert() {
|
|
48
|
+
this.maps$.next([defaultLayer]);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<c8y-title>Simple map with custom config</c8y-title>
|
|
2
|
+
|
|
3
|
+
<div class="d-flex">
|
|
4
|
+
<div class="d-flex d-col j-c-center p-r-16" style="width: 280px; height: 420px">
|
|
5
|
+
<button
|
|
6
|
+
class="btn btn-default btn-block"
|
|
7
|
+
(click)="mapLayerService?.changeLayer('Carto')"
|
|
8
|
+
>
|
|
9
|
+
Change to Carto layer
|
|
10
|
+
</button>
|
|
11
|
+
<button
|
|
12
|
+
class="btn btn-default btn-block"
|
|
13
|
+
(click)="mapLayerService?.changeLayer('OpenTopo')"
|
|
14
|
+
>
|
|
15
|
+
Change to OpenTopo layer
|
|
16
|
+
</button>
|
|
17
|
+
<button
|
|
18
|
+
class="btn btn-default btn-block"
|
|
19
|
+
(click)="mapLayerService?.revert()"
|
|
20
|
+
>
|
|
21
|
+
Change to default
|
|
22
|
+
</button>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="flex-grow p-relative a-s-stretch">
|
|
25
|
+
<c8y-map></c8y-map>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, inject } from '@angular/core';
|
|
3
|
+
import { CoreModule } from '@c8y/ngx-components';
|
|
4
|
+
import { AssetSelectorModule } from '@c8y/ngx-components/assets-navigator';
|
|
5
|
+
import { MapModule } from '@c8y/ngx-components/map';
|
|
6
|
+
import { MapLayerService } from './map-layer.service';
|
|
7
|
+
|
|
8
|
+
@Component({
|
|
9
|
+
selector: 'c8y-simple-map-custom-config',
|
|
10
|
+
templateUrl: './simple-map-custom-config.component.html',
|
|
11
|
+
standalone: true,
|
|
12
|
+
imports: [CommonModule, MapModule, CoreModule, AssetSelectorModule]
|
|
13
|
+
})
|
|
14
|
+
export class SimpleMapCustomConfigComponent {
|
|
15
|
+
mapLayerService = inject(MapLayerService);
|
|
16
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { NgModule } from '@angular/core';
|
|
3
|
+
import {
|
|
4
|
+
HookProviderTypes,
|
|
5
|
+
NavigatorNode,
|
|
6
|
+
hookNavigator,
|
|
7
|
+
hookRoute,
|
|
8
|
+
hookService
|
|
9
|
+
} from '@c8y/ngx-components';
|
|
10
|
+
import { MapLayerService } from './map-layer.service';
|
|
11
|
+
|
|
12
|
+
@NgModule({
|
|
13
|
+
imports: [CommonModule],
|
|
14
|
+
providers: [
|
|
15
|
+
MapLayerService,
|
|
16
|
+
hookService('mapTileLayerHook', MapLayerService, {
|
|
17
|
+
providerType: HookProviderTypes.ExistingProvider
|
|
18
|
+
}),
|
|
19
|
+
hookRoute({
|
|
20
|
+
path: 'maps/simple-with-custom-config',
|
|
21
|
+
loadComponent: () =>
|
|
22
|
+
import('./simple-map-custom-config.component').then(m => m.SimpleMapCustomConfigComponent)
|
|
23
|
+
}),
|
|
24
|
+
hookNavigator(
|
|
25
|
+
new NavigatorNode({
|
|
26
|
+
priority: 30,
|
|
27
|
+
path: 'maps/simple-with-custom-config',
|
|
28
|
+
icon: 'map-editing',
|
|
29
|
+
label: 'Simple map with custom config',
|
|
30
|
+
parent: 'Map examples'
|
|
31
|
+
})
|
|
32
|
+
)
|
|
33
|
+
]
|
|
34
|
+
})
|
|
35
|
+
export class SimpleMapCustomConfigModule {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { hookPatternMessages } from '@c8y/ngx-components';
|
|
2
|
+
|
|
3
|
+
hookPatternMessages([
|
|
4
|
+
{
|
|
5
|
+
'^Alarm: (.+) is active$': {
|
|
6
|
+
gettext: 'Active alarm for {{alarmType}} detected',
|
|
7
|
+
placeholders: {
|
|
8
|
+
alarmType: '$1'
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
'^User (.+) has logged in$': {
|
|
14
|
+
gettext: 'Welcome, {{username}}!',
|
|
15
|
+
placeholders: {
|
|
16
|
+
username: '$1'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
]);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { ExtensionFactory, hookPatternMessages, PatternMessages } from '@c8y/ngx-components';
|
|
3
|
+
|
|
4
|
+
@Injectable()
|
|
5
|
+
export class MyPatternMessagesFactory implements ExtensionFactory<PatternMessages> {
|
|
6
|
+
get() {
|
|
7
|
+
return {
|
|
8
|
+
'^Firmware update for (.+) completed$': {
|
|
9
|
+
gettext: 'Firmware update finished for device: {{deviceName}}',
|
|
10
|
+
placeholders: {
|
|
11
|
+
deviceName: '$1'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
hookPatternMessages(MyPatternMessagesFactory);
|
|
@@ -11,10 +11,11 @@ import {
|
|
|
11
11
|
@Component({
|
|
12
12
|
selector: 'pop-confirm-example',
|
|
13
13
|
template: `<c8y-title>Popover confirm</c8y-title>
|
|
14
|
-
<div class="p-24">
|
|
14
|
+
<div class="p-24 d-inline-block">
|
|
15
15
|
<button
|
|
16
16
|
class="btn btn-dot btn-dot--danger m-l-auto"
|
|
17
17
|
title="{{ 'Delete' | translate }}"
|
|
18
|
+
[attr.aria-label]="'Delete' | translate"
|
|
18
19
|
type="button"
|
|
19
20
|
(click)="triggerPopover(poConfirm)"
|
|
20
21
|
>
|
|
@@ -46,7 +47,9 @@ export class PopConfirmExampleComponent {
|
|
|
46
47
|
|
|
47
48
|
async triggerPopover(poConfirm: PopoverConfirmComponent): Promise<void> {
|
|
48
49
|
// to set the message
|
|
49
|
-
poConfirm.message = gettext(
|
|
50
|
+
poConfirm.message = gettext(
|
|
51
|
+
'Are you sure you want to delete this item? This action is irreversible.'
|
|
52
|
+
);
|
|
50
53
|
try {
|
|
51
54
|
const remove = await poConfirm.show(this.confirmRemoveColumnButtons);
|
|
52
55
|
if (!remove) {
|
|
@@ -8,9 +8,6 @@ import { CoreModule, DocLink, DocsService, gettext, QuickLinkModule } from '@c8y
|
|
|
8
8
|
class="btn-clean card text-pre-normal"
|
|
9
9
|
*ngFor="let link of quickLinks"
|
|
10
10
|
(click)="link.click ? link.click() : false"
|
|
11
|
-
c8yProductExperience
|
|
12
|
-
[actionName]="'welcomeWidgetClicked'"
|
|
13
|
-
[actionData]="{ link: link.label }"
|
|
14
11
|
>
|
|
15
12
|
<c8y-quick-link [icon]="link.icon" [label]="link.label"></c8y-quick-link>
|
|
16
13
|
</button>`,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<c8y-title>Realtime</c8y-title>
|
|
2
2
|
|
|
3
3
|
<c8y-action-bar-item itemClass="navbar-form" placement="right">
|
|
4
|
-
<div class="
|
|
5
|
-
<label for="bufferSizeOptions" translate>Maximum buffer size of notifications</label>
|
|
4
|
+
<div class="d-flex a-i-center">
|
|
5
|
+
<label class="m-0 p-r-4" for="bufferSizeOptions" translate>Maximum buffer size of notifications</label>
|
|
6
6
|
<div class="c8y-select-wrapper">
|
|
7
7
|
<select
|
|
8
8
|
id="bufferSizeOptions"
|
|
@@ -15,38 +15,47 @@
|
|
|
15
15
|
</div>
|
|
16
16
|
</c8y-action-bar-item>
|
|
17
17
|
|
|
18
|
-
<div class="
|
|
19
|
-
<div class="
|
|
20
|
-
<
|
|
21
|
-
<li *ngFor="let service of services">
|
|
22
|
-
<c8y-realtime-btn [service]="service.instance" [title]="'Toggle ' + service.className" [label]="service.className"></c8y-realtime-btn>
|
|
23
|
-
</li>
|
|
24
|
-
</ul>
|
|
25
|
-
<p>
|
|
26
|
-
Below you can find the latest {{ bufferSize }} notifications received from your tenant.
|
|
27
|
-
</p>
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
<ng-container *ngIf="(allAPIsRealtime$ | async) as notificationBuffer; else waiting">
|
|
32
|
-
<ng-container *ngIf="notificationBuffer.length; else waiting">
|
|
33
|
-
<div class="card" *ngFor="let realtimeItem of notificationBuffer; let i = index">
|
|
18
|
+
<div class="row">
|
|
19
|
+
<div class="col-md-6">
|
|
20
|
+
<div class="card">
|
|
34
21
|
<div class="card-header separator">
|
|
35
|
-
<h4
|
|
36
|
-
</div>
|
|
37
|
-
<div class="card-block">
|
|
38
|
-
<pre><code>{{ realtimeItem | json }}</code></pre>
|
|
22
|
+
<h4>Realtime services</h4>
|
|
39
23
|
</div>
|
|
24
|
+
<c8y-list-group>
|
|
25
|
+
<c8y-li *ngFor="let service of services">
|
|
26
|
+
<c8y-realtime-btn [service]="service.instance" [title]="'Toggle ' + service.className" [label]="service.className"></c8y-realtime-btn>
|
|
27
|
+
</c8y-li>
|
|
28
|
+
</c8y-list-group>
|
|
40
29
|
</div>
|
|
41
|
-
</
|
|
42
|
-
|
|
30
|
+
</div>
|
|
31
|
+
<div class="col-md-6">
|
|
32
|
+
<ng-container *ngIf="(allAPIsRealtime$ | async) as notificationBuffer; else waiting">
|
|
33
|
+
<ng-container *ngIf="notificationBuffer.length; else waiting">
|
|
34
|
+
<div class="card">
|
|
35
|
+
<div class="card-header separator">
|
|
36
|
+
<h4 class="card-title">Latest {{ bufferSize }} notifications received </h4>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="inner-scroll" style="height: 312px;">
|
|
39
|
+
<div class="card-block">
|
|
40
|
+
<div [ngClass]="{'separator-top p-t-16': i > 0}" *ngFor="let realtimeItem of notificationBuffer; let i = index">
|
|
41
|
+
<p class="m-b-8"><strong>{{ i + 1 }}. RealtimeMessage in buffer</strong></p>
|
|
42
|
+
<pre><code>{{ realtimeItem | json }}</code></pre>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</ng-container>
|
|
48
|
+
</ng-container>
|
|
43
49
|
|
|
44
|
-
<ng-template #waiting>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
<ng-template #waiting>
|
|
51
|
+
<div class="card">
|
|
52
|
+
<div class="card-block">
|
|
53
|
+
<c8y-loading></c8y-loading>
|
|
54
|
+
Waiting for the first notification to be received.
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</ng-template>
|
|
49
58
|
</div>
|
|
50
|
-
</
|
|
59
|
+
</div>
|
|
51
60
|
|
|
52
61
|
|