Commit 6131000c8c48751757bbb1601542057f16c482bd
1 parent
1702ba55
Direct access of core services from widget context. JavaScript editors code auto…
…completion and tooltips.
Showing
17 changed files
with
1487 additions
and
4 deletions
... | ... | @@ -44,7 +44,8 @@ |
44 | 44 | (ngModelChange)="onActionUpdated()" |
45 | 45 | [fillHeight]="true" |
46 | 46 | [functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'htmlTemplate', 'additionalParams', 'entityLabel']" |
47 | - [validationArgs]="[]"> | |
47 | + [validationArgs]="[]" | |
48 | + [editorCompleter]="customPrettyActionEditorCompleter"> | |
48 | 49 | </tb-js-func> |
49 | 50 | </div> |
50 | 51 | </div> | ... | ... |
... | ... | @@ -35,6 +35,7 @@ import { Store } from '@ngrx/store'; |
35 | 35 | import { AppState } from '@core/core.state'; |
36 | 36 | import { combineLatest } from 'rxjs'; |
37 | 37 | import { CustomActionDescriptor } from '@shared/models/widget.models'; |
38 | +import { CustomPrettyActionEditorCompleter } from '@home/components/widget/action/custom-action.models'; | |
38 | 39 | |
39 | 40 | @Component({ |
40 | 41 | selector: 'tb-custom-action-pretty-editor', |
... | ... | @@ -63,6 +64,8 @@ export class CustomActionPrettyEditorComponent extends PageComponent implements |
63 | 64 | @ViewChildren('rightPanel') |
64 | 65 | rightPanelElmRef: QueryList<ElementRef<HTMLElement>>; |
65 | 66 | |
67 | + customPrettyActionEditorCompleter = CustomPrettyActionEditorCompleter; | |
68 | + | |
66 | 69 | private propagateChange = (_: any) => {}; |
67 | 70 | |
68 | 71 | constructor(protected store: Store<AppState>) { | ... | ... |
... | ... | @@ -94,7 +94,8 @@ |
94 | 94 | [(ngModel)]="action.customFunction" |
95 | 95 | (ngModelChange)="notifyActionUpdated()" |
96 | 96 | [functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'htmlTemplate', 'additionalParams', 'entityLabel']" |
97 | - [validationArgs]="[]"> | |
97 | + [validationArgs]="[]" | |
98 | + [editorCompleter]="customPrettyActionEditorCompleter"> | |
98 | 99 | </tb-js-func> |
99 | 100 | </mat-tab> |
100 | 101 | </mat-tab-group> | ... | ... |
... | ... | @@ -36,6 +36,7 @@ import * as ace from 'ace-builds'; |
36 | 36 | import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; |
37 | 37 | import { css_beautify, html_beautify } from 'js-beautify'; |
38 | 38 | import { ResizeObserver } from '@juggle/resize-observer'; |
39 | +import { CustomPrettyActionEditorCompleter } from '@home/components/widget/action/custom-action.models'; | |
39 | 40 | |
40 | 41 | @Component({ |
41 | 42 | selector: 'tb-custom-action-pretty-resources-tabs', |
... | ... | @@ -70,6 +71,8 @@ export class CustomActionPrettyResourcesTabsComponent extends PageComponent impl |
70 | 71 | cssEditor: ace.Ace.Editor; |
71 | 72 | setValuesPending = false; |
72 | 73 | |
74 | + customPrettyActionEditorCompleter = CustomPrettyActionEditorCompleter; | |
75 | + | |
73 | 76 | constructor(protected store: Store<AppState>, |
74 | 77 | private translate: TranslateService, |
75 | 78 | private raf: RafService) { | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2020 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { TbEditorCompleter, TbEditorCompletions } from '@shared/models/ace/completion.models'; | |
18 | +import { widgetContextCompletions } from '@shared/models/ace/widget-completion.models'; | |
19 | +import { entityIdHref, entityTypeHref, serviceCompletions } from '@shared/models/ace/service-completion.models'; | |
20 | + | |
21 | +const customActionCompletions: TbEditorCompletions = { | |
22 | + ...{ | |
23 | + $event: { | |
24 | + meta: 'argument', | |
25 | + type: 'Event', | |
26 | + description: 'The DOM event that triggered this action.' | |
27 | + }, | |
28 | + widgetContext: widgetContextCompletions.ctx, | |
29 | + entityId: { | |
30 | + meta: 'argument', | |
31 | + type: entityIdHref, | |
32 | + description: 'Id of the entity for which the action was triggered.', | |
33 | + children: { | |
34 | + id: { | |
35 | + meta: 'property', | |
36 | + type: 'string', | |
37 | + description: 'UUID Id string' | |
38 | + }, | |
39 | + entityType: { | |
40 | + meta: 'property', | |
41 | + type: entityTypeHref, | |
42 | + description: 'Entity type' | |
43 | + } | |
44 | + } | |
45 | + }, | |
46 | + entityName: { | |
47 | + meta: 'argument', | |
48 | + type: 'string', | |
49 | + description: 'Name of the entity for which the action was triggered.' | |
50 | + }, | |
51 | + additionalParams: { | |
52 | + meta: 'argument', | |
53 | + type: 'object', | |
54 | + description: 'Optional object holding additional information.' | |
55 | + }, | |
56 | + entityLabel: { | |
57 | + meta: 'argument', | |
58 | + type: 'string', | |
59 | + description: 'Label of the entity for which the action was triggered.' | |
60 | + } | |
61 | + }, | |
62 | + ...serviceCompletions | |
63 | +}; | |
64 | + | |
65 | +const customPrettyActionCompletions: TbEditorCompletions = { | |
66 | + ...{ | |
67 | + htmlTemplate: { | |
68 | + meta: 'argument', | |
69 | + type: 'string', | |
70 | + description: 'HTML template used to render custom dialog.' | |
71 | + } | |
72 | + }, | |
73 | + ...customActionCompletions | |
74 | +} | |
75 | + | |
76 | +export const CustomActionEditorCompleter = new TbEditorCompleter(customActionCompletions); | |
77 | +export const CustomPrettyActionEditorCompleter = new TbEditorCompleter(customPrettyActionCompletions); | ... | ... |
... | ... | @@ -135,6 +135,7 @@ |
135 | 135 | formControlName="customFunction" |
136 | 136 | [functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']" |
137 | 137 | [validationArgs]="[]" |
138 | + [editorCompleter]="customActionEditorCompleter" | |
138 | 139 | ></tb-js-func> |
139 | 140 | </ng-template> |
140 | 141 | <ng-template [ngSwitchCase]="widgetActionType.customPretty"> | ... | ... |
... | ... | @@ -43,6 +43,7 @@ import { map, mergeMap, startWith, tap } from 'rxjs/operators'; |
43 | 43 | import { DashboardService } from '@core/http/dashboard.service'; |
44 | 44 | import { Dashboard } from '@shared/models/dashboard.models'; |
45 | 45 | import { DashboardUtilsService } from '@core/services/dashboard-utils.service'; |
46 | +import { CustomActionEditorCompleter } from '@home/components/widget/action/custom-action.models'; | |
46 | 47 | |
47 | 48 | export interface WidgetActionDialogData { |
48 | 49 | isAdd: boolean; |
... | ... | @@ -76,6 +77,8 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia |
76 | 77 | targetDashboardStateSearchText = ''; |
77 | 78 | selectedDashboardStateIds: Observable<Array<string>>; |
78 | 79 | |
80 | + customActionEditorCompleter = CustomActionEditorCompleter; | |
81 | + | |
79 | 82 | submitted = false; |
80 | 83 | |
81 | 84 | constructor(protected store: Store<AppState>, | ... | ... |
... | ... | @@ -19,7 +19,7 @@ import { Inject, Injector, OnDestroy, OnInit } from '@angular/core'; |
19 | 19 | import { Store } from '@ngrx/store'; |
20 | 20 | import { AppState } from '@core/core.state'; |
21 | 21 | import { IDynamicWidgetComponent, WidgetContext } from '@home/models/widget-component.models'; |
22 | -import { HttpErrorResponse } from '@angular/common/http'; | |
22 | +import { HttpClient, HttpErrorResponse } from '@angular/common/http'; | |
23 | 23 | import { RafService } from '@core/services/raf.service'; |
24 | 24 | import { |
25 | 25 | NotificationHorizontalPosition, |
... | ... | @@ -27,6 +27,19 @@ import { |
27 | 27 | NotificationVerticalPosition |
28 | 28 | } from '@core/notification/notification.models'; |
29 | 29 | import { FormBuilder, Validators } from '@angular/forms'; |
30 | +import { DeviceService } from '@core/http/device.service'; | |
31 | +import { AssetService } from '@core/http/asset.service'; | |
32 | +import { EntityViewService } from '@core/http/entity-view.service'; | |
33 | +import { CustomerService } from '@core/http/customer.service'; | |
34 | +import { DashboardService } from '@core/http/dashboard.service'; | |
35 | +import { UserService } from '@core/http/user.service'; | |
36 | +import { AttributeService } from '@core/http/attribute.service'; | |
37 | +import { EntityRelationService } from '@core/http/entity-relation.service'; | |
38 | +import { EntityService } from '@core/http/entity.service'; | |
39 | +import { DialogService } from '@core/services/dialog.service'; | |
40 | +import { CustomDialogService } from '@home/components/widget/dialog/custom-dialog.service'; | |
41 | +import { DatePipe } from '@angular/common'; | |
42 | +import { TranslateService } from '@ngx-translate/core'; | |
30 | 43 | |
31 | 44 | export class DynamicWidgetComponent extends PageComponent implements IDynamicWidgetComponent, OnInit, OnDestroy { |
32 | 45 | |
... | ... | @@ -47,6 +60,21 @@ export class DynamicWidgetComponent extends PageComponent implements IDynamicWid |
47 | 60 | @Inject('errorMessages') public readonly errorMessages: string[]) { |
48 | 61 | super(store); |
49 | 62 | this.ctx.$injector = $injector; |
63 | + this.ctx.deviceService = $injector.get(DeviceService); | |
64 | + this.ctx.assetService = $injector.get(AssetService); | |
65 | + this.ctx.entityViewService = $injector.get(EntityViewService); | |
66 | + this.ctx.customerService = $injector.get(CustomerService); | |
67 | + this.ctx.dashboardService = $injector.get(DashboardService); | |
68 | + this.ctx.userService = $injector.get(UserService); | |
69 | + this.ctx.attributeService = $injector.get(AttributeService); | |
70 | + this.ctx.entityRelationService = $injector.get(EntityRelationService); | |
71 | + this.ctx.entityService = $injector.get(EntityService); | |
72 | + this.ctx.dialogs = $injector.get(DialogService); | |
73 | + this.ctx.customDialog = $injector.get(CustomDialogService); | |
74 | + this.ctx.date = $injector.get(DatePipe); | |
75 | + this.ctx.translate = $injector.get(TranslateService); | |
76 | + this.ctx.http = $injector.get(HttpClient); | |
77 | + | |
50 | 78 | this.ctx.$scope = this; |
51 | 79 | if (this.ctx.defaultSubscription) { |
52 | 80 | this.executingRpcRequest = this.ctx.defaultSubscription.executingRpcRequest; | ... | ... |
... | ... | @@ -26,11 +26,19 @@ import { DatePipe } from '@angular/common'; |
26 | 26 | import { UtilsService } from '@core/services/utils.service'; |
27 | 27 | import { TranslateService } from '@ngx-translate/core'; |
28 | 28 | import { HttpClient } from '@angular/common/http'; |
29 | +import { EntityViewService } from '@core/http/entity-view.service'; | |
30 | +import { CustomerService } from '@core/http/customer.service'; | |
31 | +import { DashboardService } from '@core/http/dashboard.service'; | |
32 | +import { UserService } from '@core/http/user.service'; | |
29 | 33 | |
30 | 34 | export const ServicesMap = new Map<string, Type<any>>( |
31 | 35 | [ |
32 | 36 | ['deviceService', DeviceService], |
33 | 37 | ['assetService', AssetService], |
38 | + ['entityViewService', EntityViewService], | |
39 | + ['customerService', CustomerService], | |
40 | + ['dashboardService', DashboardService], | |
41 | + ['userService', UserService], | |
34 | 42 | ['attributeService', AttributeService], |
35 | 43 | ['entityRelationService', EntityRelationService], |
36 | 44 | ['entityService', EntityService], | ... | ... |
... | ... | @@ -43,7 +43,7 @@ import { |
43 | 43 | WidgetSubscriptionApi |
44 | 44 | } from '@core/api/widget-api.models'; |
45 | 45 | import { ChangeDetectorRef, ComponentFactory, Injector, NgZone, Type } from '@angular/core'; |
46 | -import { HttpErrorResponse } from '@angular/common/http'; | |
46 | +import { HttpClient, HttpErrorResponse } from '@angular/common/http'; | |
47 | 47 | import { RafService } from '@core/services/raf.service'; |
48 | 48 | import { WidgetTypeId } from '@shared/models/id/widget-type-id'; |
49 | 49 | import { TenantId } from '@shared/models/id/tenant-id'; |
... | ... | @@ -60,6 +60,19 @@ import { |
60 | 60 | import { ActionNotificationShow } from '@core/notification/notification.actions'; |
61 | 61 | import { AuthUser } from '@shared/models/user.model'; |
62 | 62 | import { getCurrentAuthUser } from '@core/auth/auth.selectors'; |
63 | +import { DeviceService } from '@core/http/device.service'; | |
64 | +import { AssetService } from '@core/http/asset.service'; | |
65 | +import { EntityViewService } from '@core/http/entity-view.service'; | |
66 | +import { CustomerService } from '@core/http/customer.service'; | |
67 | +import { DashboardService } from '@core/http/dashboard.service'; | |
68 | +import { UserService } from '@core/http/user.service'; | |
69 | +import { AttributeService } from '@core/http/attribute.service'; | |
70 | +import { EntityRelationService } from '@core/http/entity-relation.service'; | |
71 | +import { EntityService } from '@core/http/entity.service'; | |
72 | +import { DialogService } from '@core/services/dialog.service'; | |
73 | +import { CustomDialogService } from '@home/components/widget/dialog/custom-dialog.service'; | |
74 | +import { DatePipe } from '@angular/common'; | |
75 | +import { TranslateService } from '@ngx-translate/core'; | |
63 | 76 | |
64 | 77 | export interface IWidgetAction { |
65 | 78 | name: string; |
... | ... | @@ -126,6 +139,21 @@ export class WidgetContext { |
126 | 139 | } |
127 | 140 | } |
128 | 141 | |
142 | + deviceService: DeviceService; | |
143 | + assetService: AssetService; | |
144 | + entityViewService: EntityViewService; | |
145 | + customerService: CustomerService; | |
146 | + dashboardService: DashboardService; | |
147 | + userService: UserService; | |
148 | + attributeService: AttributeService; | |
149 | + entityRelationService: EntityRelationService; | |
150 | + entityService: EntityService; | |
151 | + dialogs: DialogService; | |
152 | + customDialog: CustomDialogService; | |
153 | + date: DatePipe; | |
154 | + translate: TranslateService; | |
155 | + http: HttpClient; | |
156 | + | |
129 | 157 | private changeDetectorValue: ChangeDetectorRef; |
130 | 158 | |
131 | 159 | inited = false; | ... | ... |
... | ... | @@ -47,6 +47,7 @@ import { |
47 | 47 | import { Subscription } from 'rxjs'; |
48 | 48 | import { ResizeObserver } from '@juggle/resize-observer'; |
49 | 49 | import Timeout = NodeJS.Timeout; |
50 | +import { widgetEditorCompleter } from '@home/pages/widget/widget-editor.models'; | |
50 | 51 | |
51 | 52 | // @dynamic |
52 | 53 | @Component({ |
... | ... | @@ -319,6 +320,7 @@ export class WidgetEditorComponent extends PageComponent implements OnInit, OnDe |
319 | 320 | this.jsEditor.on('change', () => { |
320 | 321 | this.cleanupJsErrors(); |
321 | 322 | }); |
323 | + this.jsEditor.completers = [widgetEditorCompleter, ...(this.jsEditor.completers || [])]; | |
322 | 324 | this.setAceEditorValues(); |
323 | 325 | } |
324 | 326 | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2020 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { TbEditorCompleter, TbEditorCompletions } from '@shared/models/ace/completion.models'; | |
18 | +import { widgetContextCompletions } from '@shared/models/ace/widget-completion.models'; | |
19 | +import { serviceCompletions } from '@shared/models/ace/service-completion.models'; | |
20 | + | |
21 | +const widgetEditorCompletions: TbEditorCompletions = { | |
22 | + ... {self: { | |
23 | + description: 'Built-in variable <b>self</b> that is a reference to the widget instance', | |
24 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L350">WidgetTypeInstance</a>', | |
25 | + meta: 'object', | |
26 | + children: { | |
27 | + ...{ | |
28 | + onInit: { | |
29 | + description: 'The first function which is called when widget is ready for initialization.<br>Should be used to prepare widget DOM, process widget settings and initial subscription information.', | |
30 | + meta: 'function' | |
31 | + }, | |
32 | + onDataUpdated: { | |
33 | + description: 'Called when the new data is available from the widget subscription.<br>Latest data can be accessed from ' + | |
34 | + 'the <code>defaultSubscription</code> property of <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L83">widget context (<code>ctx</code>)</a>.', | |
35 | + meta: 'function' | |
36 | + }, | |
37 | + onResize: { | |
38 | + description: 'Called when widget container is resized. Latest <code>width</code> and <code>height</code> can be obtained from <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L83">widget context (<code>ctx</code>)</a>.', | |
39 | + meta: 'function' | |
40 | + }, | |
41 | + onEditModeChanged: { | |
42 | + description: 'Called when dashboard editing mode is changed. Latest mode is handled by <code>isEdit</code> property of <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L83">widget context (<code>ctx</code>)</a>.', | |
43 | + meta: 'function' | |
44 | + }, | |
45 | + onMobileModeChanged: { | |
46 | + description: 'Called when dashboard view width crosses mobile breakpoint. Latest state is handled by <code>isMobile</code> property of <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L83">widget context (<code>ctx</code>)</a>.', | |
47 | + meta: 'function' | |
48 | + }, | |
49 | + onDestroy: { | |
50 | + description: 'Called when widget element is destroyed. Should be used to cleanup all resources if necessary.', | |
51 | + meta: 'function' | |
52 | + }, | |
53 | + getSettingsSchema: { | |
54 | + description: 'Optional function returning widget settings schema json as alternative to <b>Settings tab</b> of <a href="https://thingsboard.io/docs/user-guide/contribution/widgets-development/#settings-schema-section">Settings schema section</a>.', | |
55 | + meta: 'function', | |
56 | + return: { | |
57 | + description: 'An widget settings schema json', | |
58 | + type: 'object' | |
59 | + } | |
60 | + }, | |
61 | + getDataKeySettingsSchema: { | |
62 | + description: 'Optional function returning particular data key settings schema json as alternative to <b>Data key settings schema</b> of <a href="https://thingsboard.io/docs/user-guide/contribution/widgets-development/#settings-schema-section">Settings schema section</a>.', | |
63 | + meta: 'function', | |
64 | + return: { | |
65 | + description: 'A particular data key settings schema json', | |
66 | + type: 'object' | |
67 | + } | |
68 | + }, | |
69 | + typeParameters: { | |
70 | + description: 'Returns object describing widget datasource parameters.', | |
71 | + meta: 'function', | |
72 | + return: { | |
73 | + description: 'An object describing widget datasource parameters.', | |
74 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/widget.models.ts#L146">WidgetTypeParameters</a>' | |
75 | + } | |
76 | + }, | |
77 | + actionSources: { | |
78 | + description: 'Returns map describing available widget action sources used to define user actions.', | |
79 | + meta: 'function', | |
80 | + return: { | |
81 | + description: 'A map of action sources by action source id.', | |
82 | + type: '{[actionSourceId: string]: <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/widget.models.ts#L118">WidgetActionSource</a>}' | |
83 | + } | |
84 | + } | |
85 | + }, | |
86 | + ...widgetContextCompletions | |
87 | + } | |
88 | + }}, | |
89 | + ...widgetContextCompletions, | |
90 | + ...serviceCompletions | |
91 | +}; | |
92 | + | |
93 | +export const widgetEditorCompleter = new TbEditorCompleter(widgetEditorCompletions); | ... | ... |
... | ... | @@ -35,6 +35,8 @@ import { guid, isUndefined } from '@app/core/utils'; |
35 | 35 | import { TranslateService } from '@ngx-translate/core'; |
36 | 36 | import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; |
37 | 37 | import { ResizeObserver } from '@juggle/resize-observer'; |
38 | +import { TbEditorCompleter } from '@shared/models/ace/completion.models'; | |
39 | +import { widgetEditorCompleter } from '@home/pages/widget/widget-editor.models'; | |
38 | 40 | |
39 | 41 | @Component({ |
40 | 42 | selector: 'tb-js-func', |
... | ... | @@ -77,6 +79,8 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor, |
77 | 79 | |
78 | 80 | @Input() fillHeight: boolean; |
79 | 81 | |
82 | + @Input() editorCompleter: TbEditorCompleter; | |
83 | + | |
80 | 84 | private noValidateValue: boolean; |
81 | 85 | get noValidate(): boolean { |
82 | 86 | return this.noValidateValue; |
... | ... | @@ -153,6 +157,9 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor, |
153 | 157 | this.cleanupJsErrors(); |
154 | 158 | this.updateView(); |
155 | 159 | }); |
160 | + if (this.editorCompleter) { | |
161 | + this.jsEditor.completers = [this.editorCompleter, ...(this.jsEditor.completers || [])]; | |
162 | + } | |
156 | 163 | this.editorResize$ = new ResizeObserver(() => { |
157 | 164 | this.onAceEditorResize(); |
158 | 165 | }); | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2020 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import * as ace from 'ace-builds'; | |
18 | + | |
19 | +export type tbMetaType = 'object' | 'function' | 'service' | 'property' | 'argument'; | |
20 | + | |
21 | +export type TbEditorCompletions = {[name: string]: TbEditorCompletion}; | |
22 | + | |
23 | +export interface FunctionArgType { | |
24 | + type?: string; | |
25 | + description?: string; | |
26 | +} | |
27 | + | |
28 | +export interface FunctionArg extends FunctionArgType { | |
29 | + name: string; | |
30 | + type?: string; | |
31 | + description?: string; | |
32 | + optional?: boolean; | |
33 | +} | |
34 | + | |
35 | +export interface TbEditorCompletion { | |
36 | + meta: tbMetaType; | |
37 | + description?: string; | |
38 | + type?: string; | |
39 | + args?: FunctionArg[]; | |
40 | + return?: FunctionArgType; | |
41 | + children?: TbEditorCompletions; | |
42 | +} | |
43 | + | |
44 | +interface TbEditorAceCompletion extends ace.Ace.Completion { | |
45 | + isTbEditorAceCompletion: true; | |
46 | + snippet: string; | |
47 | + description?: string; | |
48 | + type?: string; | |
49 | + args?: FunctionArg[]; | |
50 | + return?: FunctionArgType; | |
51 | +} | |
52 | + | |
53 | +export class TbEditorCompleter implements ace.Ace.Completer { | |
54 | + | |
55 | + identifierRegexps: RegExp[] = [ | |
56 | + /[a-zA-Z_0-9\$\-\u00A2-\u2000\u2070-\uFFFF.]/ | |
57 | + ]; | |
58 | + | |
59 | + constructor(private editorCompletions: TbEditorCompletions) { | |
60 | + } | |
61 | + | |
62 | + getCompletions(editor: ace.Ace.Editor, session: ace.Ace.EditSession, | |
63 | + position: ace.Ace.Point, prefix: string, callback: ace.Ace.CompleterCallback): void { | |
64 | + const result = this.prepareCompletions(prefix); | |
65 | + if (result) { | |
66 | + callback(null, result); | |
67 | + } | |
68 | + } | |
69 | + | |
70 | + private resolvePath(prefix: string): string[] { | |
71 | + if (!prefix || !prefix.length) { | |
72 | + return []; | |
73 | + } | |
74 | + let parts = prefix.split('.'); | |
75 | + if (parts.length) { | |
76 | + parts.pop(); | |
77 | + } else { | |
78 | + parts = []; | |
79 | + } | |
80 | + let currentCompletions = this.editorCompletions; | |
81 | + for (const part of parts) { | |
82 | + if (currentCompletions[part]) { | |
83 | + currentCompletions = currentCompletions[part].children; | |
84 | + if (!currentCompletions) { | |
85 | + return null; | |
86 | + } | |
87 | + } else { | |
88 | + return null; | |
89 | + } | |
90 | + } | |
91 | + return parts; | |
92 | + } | |
93 | + | |
94 | + private prepareCompletions(prefix: string): ace.Ace.Completion[] { | |
95 | + const path = this.resolvePath(prefix); | |
96 | + if (path !== null) { | |
97 | + return this.toAceCompletionsList(this.editorCompletions, path); | |
98 | + } else { | |
99 | + return []; | |
100 | + } | |
101 | + } | |
102 | + | |
103 | + private toAceCompletionsList(completions: TbEditorCompletions, parentPath: string[]): ace.Ace.Completion[] { | |
104 | + const result: ace.Ace.Completion[] = []; | |
105 | + let targetCompletions = completions; | |
106 | + let parentPrefix = ''; | |
107 | + if (parentPath.length) { | |
108 | + parentPrefix = parentPath.join('.') + '.'; | |
109 | + for (const path of parentPath) { | |
110 | + targetCompletions = targetCompletions[path].children; | |
111 | + } | |
112 | + } | |
113 | + for (const key of Object.keys(targetCompletions)) { | |
114 | + result.push(this.toAceCompletion(key, targetCompletions[key], parentPrefix)); | |
115 | + } | |
116 | + return result; | |
117 | + } | |
118 | + | |
119 | + private toAceCompletion(name: string, completion: TbEditorCompletion, parentPrefix: string): ace.Ace.Completion { | |
120 | + const aceCompletion: TbEditorAceCompletion = { | |
121 | + isTbEditorAceCompletion: true, | |
122 | + snippet: parentPrefix + name, | |
123 | + name, | |
124 | + caption: parentPrefix + name, | |
125 | + score: 100000, | |
126 | + value: parentPrefix + name, | |
127 | + meta: completion.meta, | |
128 | + type: completion.type, | |
129 | + description: completion.description, | |
130 | + args: completion.args, | |
131 | + return: completion.return | |
132 | + }; | |
133 | + return aceCompletion; | |
134 | + } | |
135 | + | |
136 | + getDocTooltip(completion: TbEditorAceCompletion) { | |
137 | + if (completion && completion.isTbEditorAceCompletion) { | |
138 | + return { | |
139 | + docHTML: this.createDocHTML(completion) | |
140 | + }; | |
141 | + } | |
142 | + } | |
143 | + | |
144 | + private createDocHTML(completion: TbEditorAceCompletion): string { | |
145 | + let title = `<b>${completion.name}</b>`; | |
146 | + if (completion.meta === 'function') { | |
147 | + title += '('; | |
148 | + if (completion.args) { | |
149 | + const strArgs: string[] = []; | |
150 | + for (const arg of completion.args) { | |
151 | + let strArg = `${arg.name}`; | |
152 | + if (arg.optional) { | |
153 | + strArg += '?'; | |
154 | + } | |
155 | + if (arg.type) { | |
156 | + strArg += `: ${arg.type}`; | |
157 | + } | |
158 | + strArgs.push(strArg); | |
159 | + } | |
160 | + title += strArgs.join(', '); | |
161 | + } | |
162 | + title += '): '; | |
163 | + if (completion.return) { | |
164 | + title += completion.return.type; | |
165 | + } else { | |
166 | + title += 'void'; | |
167 | + } | |
168 | + } else { | |
169 | + title += `: ${completion.type ? completion.type : completion.meta}`; | |
170 | + } | |
171 | + let html = `<div class="tb-ace-doc-tooltip"><code class="title">${title}</code>`; | |
172 | + if (completion.description) { | |
173 | + html += `<hr><div>${completion.description}</div>`; | |
174 | + } | |
175 | + if (completion.args || completion.return) { | |
176 | + let functionInfoBlock = '<div class="tb-function-info">'; | |
177 | + if (completion.args) { | |
178 | + functionInfoBlock += '<div class="tb-api-title">Parameters</div>' | |
179 | + let argsTable = '<table class="tb-api-table"><tbody>'; | |
180 | + const strArgs: string[] = []; | |
181 | + for (const arg of completion.args) { | |
182 | + let strArg = `<tr><td class="arg-name"><code>${arg.name}`; | |
183 | + if (arg.optional) { | |
184 | + strArg += ' (optional)'; | |
185 | + } | |
186 | + strArg += '</code></td><td>'; | |
187 | + if (arg.type) { | |
188 | + strArg += `<code>${arg.type}</code>` | |
189 | + } | |
190 | + strArg += '</td><td class="arg-description">'; | |
191 | + if (arg.description) { | |
192 | + strArg += `${arg.description}`; | |
193 | + } | |
194 | + strArg += '</td></tr>'; | |
195 | + strArgs.push(strArg); | |
196 | + } | |
197 | + argsTable += strArgs.join('') + '</tbody></table>'; | |
198 | + functionInfoBlock += argsTable; | |
199 | + } | |
200 | + if (completion.return) { | |
201 | + let returnStr = '<div class="tb-api-title">Returns</div>'; | |
202 | + returnStr += `<div class="tb-function-return"><code>${completion.return.type}</code>`; | |
203 | + if (completion.return.description) { | |
204 | + returnStr += `: ${completion.return.description}`; | |
205 | + } | |
206 | + returnStr += '</div>'; | |
207 | + functionInfoBlock += returnStr; | |
208 | + } | |
209 | + functionInfoBlock += '</div>'; | |
210 | + html += functionInfoBlock; | |
211 | + } | |
212 | + html += '</div>'; | |
213 | + return html; | |
214 | + } | |
215 | +} | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2020 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { FunctionArg, FunctionArgType, TbEditorCompletions } from '@shared/models/ace/completion.models'; | |
18 | + | |
19 | +export const entityIdHref = '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/id/entity-id.ts#L20">EntityId</a>'; | |
20 | + | |
21 | +export const entityTypeHref = '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/entity-type.models.ts#L36">EntityType</a>'; | |
22 | + | |
23 | +export const pageDataHref = '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/page/page-data.ts#L17">PageData</a>'; | |
24 | + | |
25 | +export const deviceInfoHref = '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/device.models.ts#L33">DeviceInfo</a>'; | |
26 | + | |
27 | +export const deviceHref = '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/device.models.ts#L24">Device</a>'; | |
28 | + | |
29 | +export const deviceCredentialsHref = '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/device.models.ts#L50">DeviceCredentials</a>'; | |
30 | + | |
31 | +export const pageLinkArg: FunctionArg = { | |
32 | + name: 'pageLink', | |
33 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/page/page-link.ts#L68">PageLink</a>', | |
34 | + description: 'Page link object used to perform paginated request.' | |
35 | +}; | |
36 | + | |
37 | +export const requestConfigArg: FunctionArg = { | |
38 | + name: 'config', | |
39 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/http-utils.ts#L21">RequestConfig</a>', | |
40 | + description: 'HTTP request configuration.', | |
41 | + optional: true | |
42 | +}; | |
43 | + | |
44 | +export function observableReturnType(objectType: string): FunctionArgType { | |
45 | + return { | |
46 | + type: `Observable<${objectType}>`, | |
47 | + description: `An <code>Observable</code> of <code>${objectType}</code> object.` | |
48 | + }; | |
49 | +} | |
50 | + | |
51 | +export function observableVoid(): FunctionArgType { | |
52 | + return { | |
53 | + type: `Observable<void>`, | |
54 | + description: `An <code>Observable</code>.` | |
55 | + }; | |
56 | +} | |
57 | + | |
58 | +export function observableArrayReturnType(objectType: string): FunctionArgType { | |
59 | + return { | |
60 | + type: `Observable<Array<${objectType}>>`, | |
61 | + description: `An <code>Observable</code> of array of <code>${objectType}</code> objects.` | |
62 | + }; | |
63 | +} | |
64 | + | |
65 | +export function observablePageDataReturnType(objectType: string): FunctionArgType { | |
66 | + return { | |
67 | + type: `Observable<${pageDataHref}<${objectType}>>`, | |
68 | + description: `An <code>Observable</code> of page result as a <code>${pageDataHref}</code> holding array of <code>${objectType}</code> objects.` | |
69 | + }; | |
70 | +} | |
71 | + | |
72 | +export const serviceCompletions: TbEditorCompletions = { | |
73 | + deviceService: { | |
74 | + description: 'Device Service API<br>' + | |
75 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/device.service.ts#L37">DeviceService</a> for API reference.', | |
76 | + meta: 'service', | |
77 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/device.service.ts#L37">DeviceService</a>', | |
78 | + children: { | |
79 | + getTenantDeviceInfos: { | |
80 | + description: 'Get tenant devices', | |
81 | + meta: 'function', | |
82 | + args: [ | |
83 | + pageLinkArg, | |
84 | + { name: 'type', type: 'string', optional: true, description: 'Device type'}, | |
85 | + requestConfigArg | |
86 | + ], | |
87 | + return: observablePageDataReturnType(deviceInfoHref) | |
88 | + }, | |
89 | + getCustomerDeviceInfos: { | |
90 | + description: 'Get customer devices', | |
91 | + meta: 'function', | |
92 | + args: [ | |
93 | + { name: 'customerId', type: 'string', description: 'Id of the customer'}, | |
94 | + pageLinkArg, | |
95 | + { name: 'type', type: 'string', optional: true, description: 'Device type'}, | |
96 | + requestConfigArg | |
97 | + ], | |
98 | + return: observablePageDataReturnType(deviceInfoHref) | |
99 | + }, | |
100 | + getDevice: { | |
101 | + description: 'Get device by id', | |
102 | + meta: 'function', | |
103 | + args: [ | |
104 | + { name: 'deviceId', type: 'string', description: 'Id of the device'}, | |
105 | + requestConfigArg | |
106 | + ], | |
107 | + return: observableReturnType(deviceHref) | |
108 | + }, | |
109 | + getDevices: { | |
110 | + description: 'Get devices by ids', | |
111 | + meta: 'function', | |
112 | + args: [ | |
113 | + { name: 'deviceIds', type: 'Array<string>', description: 'List of device ids'}, | |
114 | + requestConfigArg | |
115 | + ], | |
116 | + return: observableArrayReturnType(deviceHref) | |
117 | + }, | |
118 | + getDeviceInfo: { | |
119 | + description: 'Get device info by id', | |
120 | + meta: 'function', | |
121 | + args: [ | |
122 | + { name: 'deviceId', type: 'string', description: 'Id of the device'}, | |
123 | + requestConfigArg | |
124 | + ], | |
125 | + return: observableReturnType(deviceInfoHref) | |
126 | + }, | |
127 | + saveDevice: { | |
128 | + description: 'Save device', | |
129 | + meta: 'function', | |
130 | + args: [ | |
131 | + { name: 'device', type: deviceHref, description: 'Device object to save'}, | |
132 | + requestConfigArg | |
133 | + ], | |
134 | + return: observableReturnType(deviceHref) | |
135 | + }, | |
136 | + deleteDevice: { | |
137 | + description: 'Delete device by id', | |
138 | + meta: 'function', | |
139 | + args: [ | |
140 | + { name: 'deviceId', type: 'string', description: 'Id of the device'}, | |
141 | + requestConfigArg | |
142 | + ], | |
143 | + return: observableVoid() | |
144 | + }, | |
145 | + getDeviceTypes: { | |
146 | + description: 'Get all available devices types', | |
147 | + meta: 'function', | |
148 | + args: [ | |
149 | + requestConfigArg | |
150 | + ], | |
151 | + return: observableArrayReturnType('<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/entity-type.models.ts#L295">EntitySubtype</a>') | |
152 | + }, | |
153 | + getDeviceCredentials: { | |
154 | + description: 'Get device credentials by device id', | |
155 | + meta: 'function', | |
156 | + args: [ | |
157 | + { name: 'deviceId', type: 'string', description: 'Id of the device'}, | |
158 | + { name: 'sync', type: 'boolean', description: 'Whether to execute HTTP request synchronously (false by default)', optional: true}, | |
159 | + requestConfigArg | |
160 | + ], | |
161 | + return: observableReturnType(deviceCredentialsHref) | |
162 | + }, | |
163 | + saveDeviceCredentials: { | |
164 | + description: 'Save device credentials', | |
165 | + meta: 'function', | |
166 | + args: [ | |
167 | + { name: 'deviceCredentials', type: deviceCredentialsHref, description: 'Device credentials object to save'}, | |
168 | + requestConfigArg | |
169 | + ], | |
170 | + return: observableReturnType(deviceCredentialsHref) | |
171 | + }, | |
172 | + makeDevicePublic: { | |
173 | + description: 'Make device public (available from public dashboard)', | |
174 | + meta: 'function', | |
175 | + args: [ | |
176 | + { name: 'deviceId', type: 'string', description: 'Id of the device'}, | |
177 | + requestConfigArg | |
178 | + ], | |
179 | + return: observableReturnType(deviceHref) | |
180 | + }, | |
181 | + assignDeviceToCustomer: { | |
182 | + description: 'Assign device to specific customer', | |
183 | + meta: 'function', | |
184 | + args: [ | |
185 | + { name: 'customerId', type: 'string', description: 'Id of the customer'}, | |
186 | + { name: 'deviceId', type: 'string', description: 'Id of the device'}, | |
187 | + requestConfigArg | |
188 | + ], | |
189 | + return: observableReturnType(deviceHref) | |
190 | + }, | |
191 | + unassignDeviceFromCustomer: { | |
192 | + description: 'Unassign device from any customer', | |
193 | + meta: 'function', | |
194 | + args: [ | |
195 | + { name: 'deviceId', type: 'string', description: 'Id of the device'}, | |
196 | + requestConfigArg | |
197 | + ], | |
198 | + return: observableVoid() | |
199 | + }, | |
200 | + sendOneWayRpcCommand: { | |
201 | + description: 'Send one way (without response) RPC command to the device.', | |
202 | + meta: 'function', | |
203 | + args: [ | |
204 | + { name: 'deviceId', type: 'string', description: 'Id of the device'}, | |
205 | + { name: 'requestBody', type: 'object', description: 'Request body to be sent to device'}, | |
206 | + requestConfigArg | |
207 | + ], | |
208 | + return: { | |
209 | + type: `Observable<any>`, | |
210 | + description: `A command execution <code>Observable</code>.` | |
211 | + } | |
212 | + }, | |
213 | + sendTwoWayRpcCommand: { | |
214 | + description: 'Sends two way (with response) RPC command to the device.', | |
215 | + meta: 'function', | |
216 | + args: [ | |
217 | + { name: 'deviceId', type: 'string', description: 'Id of the device'}, | |
218 | + { name: 'requestBody', type: 'object', description: 'Request body to be sent to device'}, | |
219 | + requestConfigArg | |
220 | + ], | |
221 | + return: { | |
222 | + type: `Observable<any>`, | |
223 | + description: `A command execution <code>Observable</code> of response body.` | |
224 | + } | |
225 | + }, | |
226 | + findByQuery: { | |
227 | + description: 'Find devices by search query', | |
228 | + meta: 'function', | |
229 | + args: [ | |
230 | + { name: 'query', type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/device.models.ts#L57">DeviceSearchQuery</a>', | |
231 | + description: 'Device search query object'}, | |
232 | + requestConfigArg | |
233 | + ], | |
234 | + return: observableArrayReturnType(deviceHref) | |
235 | + }, | |
236 | + findByName: { | |
237 | + description: 'Find device by name', | |
238 | + meta: 'function', | |
239 | + args: [ | |
240 | + { name: 'deviceName', type: 'string', | |
241 | + description: 'Search device name'}, | |
242 | + requestConfigArg | |
243 | + ], | |
244 | + return: observableReturnType(deviceHref) | |
245 | + }, | |
246 | + claimDevice: { | |
247 | + description: 'Send claim device request', | |
248 | + meta: 'function', | |
249 | + args: [ | |
250 | + { name: 'deviceName', type: 'string', | |
251 | + description: 'Claiming device name'}, | |
252 | + requestConfigArg | |
253 | + ], | |
254 | + return: observableReturnType('<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/device.models.ts#L71">ClaimResult</a>') | |
255 | + }, | |
256 | + unclaimDevice: { | |
257 | + description: 'Send un-claim device request', | |
258 | + meta: 'function', | |
259 | + args: [ | |
260 | + { name: 'deviceName', type: 'string', | |
261 | + description: 'Device name to un-claim'}, | |
262 | + requestConfigArg | |
263 | + ], | |
264 | + return: observableVoid() | |
265 | + } | |
266 | + } | |
267 | + }, | |
268 | + assetService: { | |
269 | + description: 'Asset Service API<br>' + | |
270 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/asset.service.ts#L29">AssetService</a> for API reference.', | |
271 | + meta: 'service', | |
272 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/asset.service.ts#L29">AssetService</a>' | |
273 | + }, | |
274 | + entityViewService: { | |
275 | + description: 'EntityView Service API<br>' + | |
276 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/entity-view.service.ts#L29">EntityViewService</a> for API reference.', | |
277 | + meta: 'service', | |
278 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/entity-view.service.ts#L29">EntityViewService</a>' | |
279 | + }, | |
280 | + customerService: { | |
281 | + description: 'Customer Service API<br>' + | |
282 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/customer.service.ts#L28">CustomerService</a> for API reference.', | |
283 | + meta: 'service', | |
284 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/customer.service.ts#L28">CustomerService</a>' | |
285 | + }, | |
286 | + dashboardService: { | |
287 | + description: 'Dashboard Service API<br>' + | |
288 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/dashboard.service.ts#L32">DashboardService</a> for API reference.', | |
289 | + meta: 'service', | |
290 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/dashboard.service.ts#L32">DashboardService</a>' | |
291 | + }, | |
292 | + userService: { | |
293 | + description: 'User Service API<br>' + | |
294 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/user.service.ts#L29">UserService</a> for API reference.', | |
295 | + meta: 'service', | |
296 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/user.service.ts#L29">UserService</a>' | |
297 | + }, | |
298 | + attributeService: { | |
299 | + description: 'Attribute Service API<br>' + | |
300 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/attribute.service.ts#L28">AttributeService</a> for API reference.', | |
301 | + meta: 'service', | |
302 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/attribute.service.ts#L28">AttributeService</a>' | |
303 | + }, | |
304 | + entityRelationService: { | |
305 | + description: 'Entity Relation Service API<br>' + | |
306 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/entity-relation.service.ts#L27">EntityRelationService</a> for API reference.', | |
307 | + meta: 'service', | |
308 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/entity-relation.service.ts#L27">EntityRelationService</a>' | |
309 | + }, | |
310 | + entityService: { | |
311 | + description: 'Entity Service API<br>' + | |
312 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/entity.service.ts#L64">EntityService</a> for API reference.', | |
313 | + meta: 'service', | |
314 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/http/entity.service.ts#L64">EntityService</a>' | |
315 | + }, | |
316 | + dialogs: { | |
317 | + description: 'Dialogs Service API<br>' + | |
318 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/services/dialog.service.ts#L39">DialogService</a> for API reference.', | |
319 | + meta: 'service', | |
320 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/services/dialog.service.ts#L39">DialogService</a>' | |
321 | + }, | |
322 | + customDialog: { | |
323 | + description: 'Custom Dialog Service API<br>' + | |
324 | + 'See <a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.service.ts#L33">CustomDialogService</a> for API reference.', | |
325 | + meta: 'service', | |
326 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.service.ts#L33">CustomDialogService</a>' | |
327 | + }, | |
328 | + date: { | |
329 | + description: 'Date Pipe<br>Formats a date value according to locale rules.<br>' + | |
330 | + 'See <a href="https://angular.io/api/common/DatePipe">DatePipe</a> for API reference.', | |
331 | + meta: 'service', | |
332 | + type: '<a href="https://angular.io/api/common/DatePipe">DatePipe</a>' | |
333 | + }, | |
334 | + translate: { | |
335 | + description: 'Translate Service API<br>' + | |
336 | + 'See <a href="https://github.com/ngx-translate/core#translateservice">TranslateService</a> for API reference.', | |
337 | + meta: 'service', | |
338 | + type: '<a href="https://github.com/ngx-translate/core#translateservice">TranslateService</a>' | |
339 | + }, | |
340 | + http: { | |
341 | + description: 'HTTP Client Service<br>' + | |
342 | + 'See <a href="https://angular.io/api/common/http/HttpClient">HttpClient</a> for API reference.', | |
343 | + meta: 'service', | |
344 | + type: '<a href="https://angular.io/api/common/http/HttpClient">HttpClient</a>' | |
345 | + } | |
346 | +} | ... | ... |
1 | +/// | |
2 | +/// Copyright © 2016-2020 The Thingsboard Authors | |
3 | +/// | |
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +/// you may not use this file except in compliance with the License. | |
6 | +/// You may obtain a copy of the License at | |
7 | +/// | |
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +/// | |
10 | +/// Unless required by applicable law or agreed to in writing, software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +/// See the License for the specific language governing permissions and | |
14 | +/// limitations under the License. | |
15 | +/// | |
16 | + | |
17 | +import { TbEditorCompletion, TbEditorCompletions } from '@shared/models/ace/completion.models'; | |
18 | +import { entityIdHref, serviceCompletions } from '@shared/models/ace/service-completion.models'; | |
19 | + | |
20 | +export const timewindowCompletion: TbEditorCompletion = { | |
21 | + description: 'Timewindow configuration object', | |
22 | + meta: 'property', | |
23 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/time/time.models.ts#L80">Timewindow</a>', | |
24 | + children: { | |
25 | + displayValue: { | |
26 | + description: 'Current timewindow display value.', | |
27 | + meta: 'property', | |
28 | + type: 'string' | |
29 | + }, | |
30 | + hideInterval: { | |
31 | + description: 'Whether to hide interval selection in timewindow panel.', | |
32 | + meta: 'property', | |
33 | + type: 'boolean' | |
34 | + }, | |
35 | + hideAggregation: { | |
36 | + description: 'Whether to hide aggregation selection in timewindow panel.', | |
37 | + meta: 'property', | |
38 | + type: 'boolean' | |
39 | + }, | |
40 | + hideAggInterval: { | |
41 | + description: 'Whether to hide aggregation interval selection in timewindow panel.', | |
42 | + meta: 'property', | |
43 | + type: 'boolean' | |
44 | + }, | |
45 | + selectedTab: { | |
46 | + description: 'Current selected timewindow type (0 - realtime, 1 - history).', | |
47 | + meta: 'property', | |
48 | + type: 'number' | |
49 | + }, | |
50 | + realtime: { | |
51 | + description: 'Realtime timewindow configuration object.', | |
52 | + meta: 'property', | |
53 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/time/time.models.ts#L39">IntervalWindow</a>', | |
54 | + children: { | |
55 | + interval: { | |
56 | + description: 'Timewindow aggregation interval in milliseconds', | |
57 | + meta: 'property', | |
58 | + type: 'number' | |
59 | + }, | |
60 | + timewindowMs: { | |
61 | + description: 'Timewindow interval in milliseconds', | |
62 | + meta: 'property', | |
63 | + type: 'number' | |
64 | + } | |
65 | + } | |
66 | + }, | |
67 | + history: { | |
68 | + description: 'History timewindow configuration object.', | |
69 | + meta: 'property', | |
70 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/time/time.models.ts#L49">HistoryWindow</a>', | |
71 | + children: { | |
72 | + historyType: { | |
73 | + description: 'History timewindow type (0 - last interval, 1 - fixed)', | |
74 | + meta: 'property', | |
75 | + type: 'number' | |
76 | + }, | |
77 | + interval: { | |
78 | + description: 'Timewindow aggregation interval in milliseconds', | |
79 | + meta: 'property', | |
80 | + type: 'number' | |
81 | + }, | |
82 | + timewindowMs: { | |
83 | + description: 'Timewindow interval in milliseconds', | |
84 | + meta: 'property', | |
85 | + type: 'number' | |
86 | + }, | |
87 | + fixedTimewindow: { | |
88 | + description: 'Fixed history timewindow configuration object', | |
89 | + meta: 'property', | |
90 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/time/time.models.ts#L44">FixedWindow</a>', | |
91 | + children: { | |
92 | + startTimeMs: { | |
93 | + description: 'Timewindow start time in UTC milliseconds', | |
94 | + meta: 'property', | |
95 | + type: 'number' | |
96 | + }, | |
97 | + endTimeMs: { | |
98 | + description: 'Timewindow end time in UTC milliseconds', | |
99 | + meta: 'property', | |
100 | + type: 'number' | |
101 | + } | |
102 | + } | |
103 | + } | |
104 | + } | |
105 | + }, | |
106 | + aggregation: { | |
107 | + description: 'Timewindow aggregation configuration object.', | |
108 | + meta: 'property', | |
109 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/time/time.models.ts#L74">Aggregation</a>', | |
110 | + children: { | |
111 | + interval: { | |
112 | + description: 'Aggregation interval in milliseconds', | |
113 | + meta: 'property', | |
114 | + type: 'number' | |
115 | + }, | |
116 | + type: { | |
117 | + description: 'Aggregation type', | |
118 | + meta: 'property', | |
119 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/time/time.models.ts#L54">AggregationType</a>' | |
120 | + }, | |
121 | + limit: { | |
122 | + description: 'Maximum allowed datapoints when aggregation is disabled (<code>AggregationType == \'NONE\'</code>)', | |
123 | + meta: 'property', | |
124 | + type: 'number' | |
125 | + } | |
126 | + } | |
127 | + } | |
128 | + } | |
129 | +} | |
130 | + | |
131 | +export const widgetContextCompletions: TbEditorCompletions = { | |
132 | + ctx: { | |
133 | + description: 'A reference to widget context that has all necessary API<br>and data used by widget instance.', | |
134 | + meta: 'object', | |
135 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L83">WidgetContext</a>', | |
136 | + children: { | |
137 | + ...{ | |
138 | + $container: { | |
139 | + description: 'Container element of the widget.<br>Can be used to dynamically access or modify widget DOM using jQuery API.', | |
140 | + meta: 'property', | |
141 | + type: 'jQuery Object' | |
142 | + }, | |
143 | + $scope: { | |
144 | + description: 'Reference to the current widget component.<br>Can be used to access/modify component properties when widget is built using Angular approach.', | |
145 | + meta: 'property', | |
146 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L274">IDynamicWidgetComponent</a>' | |
147 | + }, | |
148 | + width: { | |
149 | + description: 'Current width of widget container in pixels.', | |
150 | + meta: 'property', | |
151 | + type: 'number' | |
152 | + }, | |
153 | + height: { | |
154 | + description: 'Current height of widget container in pixels.', | |
155 | + meta: 'property', | |
156 | + type: 'number' | |
157 | + }, | |
158 | + isEdit: { | |
159 | + description: 'Indicates whether the dashboard is in in the view or editing state.', | |
160 | + meta: 'property', | |
161 | + type: 'boolean' | |
162 | + }, | |
163 | + isMobile: { | |
164 | + description: 'Indicates whether the dashboard view is less then 960px width (default mobile breakpoint).', | |
165 | + meta: 'property', | |
166 | + type: 'boolean' | |
167 | + }, | |
168 | + widgetConfig: { | |
169 | + description: 'Common widget configuration containing properties such as <code>color</code> (text color), <code>backgroundColor</code> (widget background color), etc.', | |
170 | + meta: 'property', | |
171 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/widget.models.ts#L341">WidgetConfig</a>', | |
172 | + children: { | |
173 | + title: { | |
174 | + description: 'Widget title.', | |
175 | + meta: 'property', | |
176 | + type: 'string' | |
177 | + }, | |
178 | + titleIcon: { | |
179 | + description: 'Widget title icon.', | |
180 | + meta: 'property', | |
181 | + type: 'string' | |
182 | + }, | |
183 | + showTitle: { | |
184 | + description: 'Whether to show widget title.', | |
185 | + meta: 'property', | |
186 | + type: 'boolean' | |
187 | + }, | |
188 | + showTitleIcon: { | |
189 | + description: 'Whether to show widget title icon.', | |
190 | + meta: 'property', | |
191 | + type: 'boolean' | |
192 | + }, | |
193 | + iconColor: { | |
194 | + description: 'Widget title icon color.', | |
195 | + meta: 'property', | |
196 | + type: 'string' | |
197 | + }, | |
198 | + iconSize: { | |
199 | + description: 'Widget title icon size.', | |
200 | + meta: 'property', | |
201 | + type: 'string' | |
202 | + }, | |
203 | + titleTooltip: { | |
204 | + description: 'Widget title tooltip content.', | |
205 | + meta: 'property', | |
206 | + type: 'string' | |
207 | + }, | |
208 | + dropShadow: { | |
209 | + description: 'Enable/disable widget card shadow.', | |
210 | + meta: 'property', | |
211 | + type: 'boolean' | |
212 | + }, | |
213 | + enableFullscreen: { | |
214 | + description: 'Whether to enable fullscreen button on widget.', | |
215 | + meta: 'property', | |
216 | + type: 'boolean' | |
217 | + }, | |
218 | + useDashboardTimewindow: { | |
219 | + description: 'Whether to use dashboard timewindow (applicable for timeseries widgets).', | |
220 | + meta: 'property', | |
221 | + type: 'boolean' | |
222 | + }, | |
223 | + displayTimewindow: { | |
224 | + description: 'Whether to display timewindow (applicable for timeseries widgets).', | |
225 | + meta: 'property', | |
226 | + type: 'boolean' | |
227 | + }, | |
228 | + showLegend: { | |
229 | + description: 'Whether to show legend.', | |
230 | + meta: 'property', | |
231 | + type: 'boolean' | |
232 | + }, | |
233 | + legendConfig: { | |
234 | + description: 'Legend configuration.', | |
235 | + meta: 'property', | |
236 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/widget.models.ts#L198">LegendConfig</a>', | |
237 | + children: { | |
238 | + position: { | |
239 | + description: 'Legend position. Possible values: <code>\'top\', \'bottom\', \'left\', \'right\'</code>', | |
240 | + meta: 'property', | |
241 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/widget.models.ts#L182">LegendPosition</a>', | |
242 | + }, | |
243 | + direction: { | |
244 | + description: 'Legend direction. Possible values: <code>\'column\', \'row\'</code>', | |
245 | + meta: 'property', | |
246 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/widget.models.ts#L170">LegendDirection</a>', | |
247 | + }, | |
248 | + showMin: { | |
249 | + description: 'Whether to display aggregated min values.', | |
250 | + meta: 'property', | |
251 | + type: 'boolean', | |
252 | + }, | |
253 | + showMax: { | |
254 | + description: 'Whether to display aggregated max values.', | |
255 | + meta: 'property', | |
256 | + type: 'boolean', | |
257 | + }, | |
258 | + showAvg: { | |
259 | + description: 'Whether to display aggregated average values.', | |
260 | + meta: 'property', | |
261 | + type: 'boolean', | |
262 | + }, | |
263 | + showTotal: { | |
264 | + description: 'Whether to display aggregated total values.', | |
265 | + meta: 'property', | |
266 | + type: 'boolean', | |
267 | + } | |
268 | + } | |
269 | + }, | |
270 | + timewindow: timewindowCompletion, | |
271 | + mobileHeight: { | |
272 | + description: 'Widget height in mobile mode.', | |
273 | + meta: 'property', | |
274 | + type: 'number' | |
275 | + }, | |
276 | + mobileOrder: { | |
277 | + description: 'Widget order in mobile mode.', | |
278 | + meta: 'property', | |
279 | + type: 'number' | |
280 | + }, | |
281 | + color: { | |
282 | + description: 'Widget text color.', | |
283 | + meta: 'property', | |
284 | + type: 'string' | |
285 | + }, | |
286 | + backgroundColor: { | |
287 | + description: 'Widget background color.', | |
288 | + meta: 'property', | |
289 | + type: 'string' | |
290 | + }, | |
291 | + padding: { | |
292 | + description: 'Widget card padding.', | |
293 | + meta: 'property', | |
294 | + type: 'string' | |
295 | + }, | |
296 | + margin: { | |
297 | + description: 'Widget card margin.', | |
298 | + meta: 'property', | |
299 | + type: 'string' | |
300 | + }, | |
301 | + widgetStyle: { | |
302 | + description: 'Widget element style object.', | |
303 | + meta: 'property', | |
304 | + type: 'object' | |
305 | + }, | |
306 | + titleStyle: { | |
307 | + description: 'Widget title element style object.', | |
308 | + meta: 'property', | |
309 | + type: 'object' | |
310 | + }, | |
311 | + units: { | |
312 | + description: 'Optional property defining units text of values displayed by widget. Useful for simple widgets like cards or gauges.', | |
313 | + meta: 'property', | |
314 | + type: 'string' | |
315 | + }, | |
316 | + decimals: { | |
317 | + description: 'Optional property defining how many positions should be used to display decimal part of the value number.', | |
318 | + meta: 'property', | |
319 | + type: 'number' | |
320 | + }, | |
321 | + actions: { | |
322 | + description: 'Map of configured widget actions.', | |
323 | + meta: 'property', | |
324 | + type: 'object' | |
325 | + }, | |
326 | + settings: { | |
327 | + description: 'Object holding widget settings according to widget type.', | |
328 | + meta: 'property', | |
329 | + type: 'object' | |
330 | + }, | |
331 | + alarmSource: { | |
332 | + description: 'Configured alarm source for alarm widget type.', | |
333 | + meta: 'property', | |
334 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/widget.models.ts#L250">Datasource</a>' | |
335 | + }, | |
336 | + alarmSearchStatus: { | |
337 | + description: 'Configured default alarm search status for alarm widget type.', | |
338 | + meta: 'property', | |
339 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/alarm.models.ts#L41">AlarmSearchStatus</a>' | |
340 | + }, | |
341 | + alarmsPollingInterval: { | |
342 | + description: 'Configured alarms polling interval for alarm widget type.', | |
343 | + meta: 'property', | |
344 | + type: 'number' | |
345 | + }, | |
346 | + alarmsMaxCountLoad: { | |
347 | + description: 'Configured maximum alarms to load for alarm widget type.', | |
348 | + meta: 'property', | |
349 | + type: 'number' | |
350 | + }, | |
351 | + alarmsFetchSize: { | |
352 | + description: 'Configured alarms page size used to load alarms.', | |
353 | + meta: 'property', | |
354 | + type: 'number' | |
355 | + }, | |
356 | + datasources: { | |
357 | + description: 'Array of configured widget datasources.', | |
358 | + meta: 'property', | |
359 | + type: 'Array<<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/widget.models.ts#L250">Datasource</a>>' | |
360 | + } | |
361 | + } | |
362 | + }, | |
363 | + settings: { | |
364 | + description: 'Widget settings containing widget specific properties according to the defined <a href="https://thingsboard.io/docs/user-guide/contribution/widgets-development/#settings-schema-section">settings json schema</a>', | |
365 | + meta: 'property', | |
366 | + type: 'object' | |
367 | + }, | |
368 | + units: { | |
369 | + description: 'Optional property defining units text of values displayed by widget. Useful for simple widgets like cards or gauges.', | |
370 | + meta: 'property', | |
371 | + type: 'string' | |
372 | + }, | |
373 | + decimals: { | |
374 | + description: 'Optional property defining how many positions should be used to display decimal part of the value number.', | |
375 | + meta: 'property', | |
376 | + type: 'number' | |
377 | + }, | |
378 | + hideTitlePanel: { | |
379 | + description: 'Manages visibility of widget title panel. Useful for widget with custom title panels or different states.', | |
380 | + meta: 'property', | |
381 | + type: 'boolean' | |
382 | + }, | |
383 | + defaultSubscription: { | |
384 | + description: 'Default widget subscription object contains all subscription information,<br>including current data, according to the widget type.', | |
385 | + meta: 'property', | |
386 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/api/widget-api.models.ts#L220">IWidgetSubscription</a>' | |
387 | + }, | |
388 | + timewindowFunctions: { | |
389 | + description: 'Object with timewindow functions used to manage widget data time frame. Can by used by Time-series or Alarm widgets.', | |
390 | + meta: 'property', | |
391 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/api/widget-api.models.ts#L45">TimewindowFunctions</a>', | |
392 | + children: { | |
393 | + onUpdateTimewindow: { | |
394 | + description: 'This function can be used to update current subscription time frame<br>to historical one identified by <code>startTimeMs</code> and <code>endTimeMs</code> arguments.', | |
395 | + meta: 'function', | |
396 | + args: [ | |
397 | + { | |
398 | + name: 'startTimeMs', | |
399 | + description: 'Timewindow start time in UTC milliseconds', | |
400 | + type: 'number' | |
401 | + }, | |
402 | + { | |
403 | + name: 'endTimeMs', | |
404 | + description: 'Timewindow end time in UTC milliseconds', | |
405 | + type: 'number' | |
406 | + } | |
407 | + ] | |
408 | + }, | |
409 | + onResetTimewindow: { | |
410 | + description: 'Resets subscription time frame to default defined by widget timewindow component<br>or dashboard timewindow depending on widget settings.', | |
411 | + meta: 'function' | |
412 | + } | |
413 | + } | |
414 | + }, | |
415 | + controlApi: { | |
416 | + description: 'Object that provides API functions for RPC (Control) widgets.', | |
417 | + meta: 'property', | |
418 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/api/widget-api.models.ts#L58">RpcApi</a>', | |
419 | + children: { | |
420 | + sendOneWayCommand: { | |
421 | + description: 'Sends one way (without response) RPC command to the device.', | |
422 | + meta: 'function', | |
423 | + args: [ | |
424 | + { | |
425 | + name: 'method', | |
426 | + description: 'RPC method name', | |
427 | + type: 'string' | |
428 | + }, | |
429 | + { | |
430 | + name: 'params', | |
431 | + description: 'RPC method params, custom json object', | |
432 | + type: 'object', | |
433 | + optional: true | |
434 | + }, | |
435 | + { | |
436 | + name: 'timeout', | |
437 | + description: 'Maximum delay in milliseconds to wait until response/acknowledgement is received.', | |
438 | + type: 'number', | |
439 | + optional: true | |
440 | + } | |
441 | + ], | |
442 | + return: { | |
443 | + description: 'A command execution Observable.', | |
444 | + type: 'Observable<any>' | |
445 | + } | |
446 | + }, | |
447 | + sendTwoWayCommand: { | |
448 | + description: 'Sends two way (with response) RPC command to the device.', | |
449 | + meta: 'function', | |
450 | + args: [ | |
451 | + { | |
452 | + name: 'method', | |
453 | + description: 'RPC method name', | |
454 | + type: 'string' | |
455 | + }, | |
456 | + { | |
457 | + name: 'params', | |
458 | + description: 'RPC method params, custom json object', | |
459 | + type: 'object', | |
460 | + optional: true | |
461 | + }, | |
462 | + { | |
463 | + name: 'timeout', | |
464 | + description: 'Maximum delay in milliseconds to wait until response/acknowledgement is received.', | |
465 | + type: 'number', | |
466 | + optional: true | |
467 | + } | |
468 | + ], | |
469 | + return: { | |
470 | + description: 'A command execution Observable of response body.', | |
471 | + type: 'Observable<any>' | |
472 | + } | |
473 | + } | |
474 | + } | |
475 | + }, | |
476 | + actionsApi: { | |
477 | + description: 'Set of API functions to work with user defined actions.', | |
478 | + meta: 'property', | |
479 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/api/widget-api.models.ts#L67">WidgetActionsApi</a>', | |
480 | + children: { | |
481 | + getActionDescriptors: { | |
482 | + description: 'Get list of action descriptors for provided <code>actionSourceId</code>.', | |
483 | + meta: 'function', | |
484 | + args: [ | |
485 | + { | |
486 | + name: 'actionSourceId', | |
487 | + description: 'Id of widget action source', | |
488 | + type: 'string' | |
489 | + } | |
490 | + ], | |
491 | + return: { | |
492 | + description: 'The list of action descriptors', | |
493 | + type: 'Array<<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/widget.models.ts#L323">WidgetActionDescriptor</a>>' | |
494 | + } | |
495 | + }, | |
496 | + handleWidgetAction: { | |
497 | + description: 'Handle action produced by particular action source.', | |
498 | + meta: 'function', | |
499 | + args: [ | |
500 | + { | |
501 | + name: '$event', | |
502 | + description: 'DOM event object associated with action.', | |
503 | + type: 'Event' | |
504 | + }, | |
505 | + { | |
506 | + name: 'descriptor', | |
507 | + description: 'An action descriptor.', | |
508 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/shared/models/widget.models.ts#L323">WidgetActionDescriptor</a>' | |
509 | + }, | |
510 | + { | |
511 | + name: 'entityId', | |
512 | + description: 'Current entity id provided by action source if available.', | |
513 | + type: entityIdHref, | |
514 | + optional: true | |
515 | + }, | |
516 | + { | |
517 | + name: 'entityName', | |
518 | + description: 'Current entity name provided by action source if available.', | |
519 | + type: 'string', | |
520 | + optional: true | |
521 | + } | |
522 | + ] | |
523 | + } | |
524 | + } | |
525 | + }, | |
526 | + stateController: { | |
527 | + description: 'Reference to Dashboard state controller, providing API to manage current dashboard state.', | |
528 | + meta: 'property', | |
529 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/api/widget-api.models.ts#L121">IStateController</a>', | |
530 | + children: { | |
531 | + openState: { | |
532 | + description: 'Navigate to new dashboard state.', | |
533 | + meta: 'function', | |
534 | + args: [ | |
535 | + { | |
536 | + name: 'id', | |
537 | + description: 'An id of the target dashboard state.', | |
538 | + type: 'string' | |
539 | + }, | |
540 | + { | |
541 | + name: 'params', | |
542 | + description: 'An object with state parameters to use by the new state.', | |
543 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/api/widget-api.models.ts#L111">StateParams</a>', | |
544 | + optional: true | |
545 | + }, | |
546 | + { | |
547 | + name: 'openRightLayout', | |
548 | + description: 'An optional boolean argument to force open right dashboard layout if present in mobile view mode.', | |
549 | + type: 'boolean', | |
550 | + optional: true | |
551 | + } | |
552 | + ] | |
553 | + }, | |
554 | + updateState: { | |
555 | + description: 'Updates current dashboard state.', | |
556 | + meta: 'function', | |
557 | + args: [ | |
558 | + { | |
559 | + name: 'id', | |
560 | + description: 'An optional id of the target dashboard state to replace current state id.', | |
561 | + type: 'string', | |
562 | + optional: true | |
563 | + }, | |
564 | + { | |
565 | + name: 'params', | |
566 | + description: 'An object with state parameters to update current state parameters.', | |
567 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/api/widget-api.models.ts#L111">StateParams</a>', | |
568 | + optional: true | |
569 | + }, | |
570 | + { | |
571 | + name: 'openRightLayout', | |
572 | + description: 'An optional boolean argument to force open right dashboard layout if present in mobile view mode.', | |
573 | + type: 'boolean', | |
574 | + optional: true | |
575 | + } | |
576 | + ] | |
577 | + }, | |
578 | + getStateId: { | |
579 | + description: 'Get current dashboard state id.', | |
580 | + meta: 'function', | |
581 | + return: { | |
582 | + description: 'current dashboard state id.', | |
583 | + type: 'string' | |
584 | + } | |
585 | + }, | |
586 | + getStateParams: { | |
587 | + description: 'Get current dashboard state parameters.', | |
588 | + meta: 'function', | |
589 | + return: { | |
590 | + description: 'current dashboard state parameters.', | |
591 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/api/widget-api.models.ts#L111">StateParams</a>' | |
592 | + } | |
593 | + }, | |
594 | + getStateParamsByStateId: { | |
595 | + description: 'Get state parameters for particular dashboard state identified by <code>id</code>.', | |
596 | + meta: 'function', | |
597 | + args: [ | |
598 | + { | |
599 | + name: 'id', | |
600 | + description: 'An id of the target dashboard state.', | |
601 | + type: 'string' | |
602 | + } | |
603 | + ], | |
604 | + return: { | |
605 | + description: 'current dashboard state parameters.', | |
606 | + type: '<a href="https://github.com/thingsboard/thingsboard/blob/13e6b10b7ab830e64d31b99614a9d95a1a25928a/ui-ngx/src/app/core/api/widget-api.models.ts#L111">StateParams</a>' | |
607 | + } | |
608 | + } | |
609 | + } | |
610 | + } | |
611 | + }, | |
612 | + ...serviceCompletions | |
613 | + } | |
614 | + } | |
615 | +} | ... | ... |
... | ... | @@ -416,6 +416,58 @@ mat-label { |
416 | 416 | } |
417 | 417 | } |
418 | 418 | |
419 | +.tb-ace-doc-tooltip { | |
420 | + code { | |
421 | + color: #444; | |
422 | + &.title { | |
423 | + font-size: 14px; | |
424 | + } | |
425 | + } | |
426 | + div.tb-function-info { | |
427 | + font-size: 14px; | |
428 | + } | |
429 | + div.tb-function-return { | |
430 | + font-size: 1rem; | |
431 | + letter-spacing: 0.03rem; | |
432 | + color: #444; | |
433 | + code { | |
434 | + font-size: 14px; | |
435 | + letter-spacing: normal; | |
436 | + } | |
437 | + } | |
438 | + div.tb-api-title { | |
439 | + font-weight: bold; | |
440 | + font-size: 16px; | |
441 | + color: #6e6e6e; | |
442 | + padding-top: 12px; | |
443 | + padding-bottom: 12px; | |
444 | + } | |
445 | + table.tb-api-table { | |
446 | + width: 100%; | |
447 | + border-collapse: collapse; | |
448 | + tr { | |
449 | + border-bottom: 1px solid #a8a8a8; | |
450 | + &:last-child { | |
451 | + border-bottom: none; | |
452 | + } | |
453 | + td { | |
454 | + font-size: 14px; | |
455 | + line-height: 1.6rem; | |
456 | + &:first-child { | |
457 | + font-weight: 600; | |
458 | + padding-left: 16px; | |
459 | + width: 20%; | |
460 | + } | |
461 | + &.arg-description { | |
462 | + font-size: 1rem; | |
463 | + letter-spacing: .03rem; | |
464 | + color: #444; | |
465 | + } | |
466 | + } | |
467 | + } | |
468 | + } | |
469 | +} | |
470 | + | |
419 | 471 | .tb-default, .tb-dark { |
420 | 472 | |
421 | 473 | /********************************* | ... | ... |