Commit 712e756e589d671d1423b3e60a51015e6f7bfd65

Authored by Volodymyr Babak
1 parent ae856411

Refactoring to simplify reading and merge

... ... @@ -21,11 +21,13 @@ export interface SysParamsState {
21 21 allowedDashboardIds: string[];
22 22 edgesSupportEnabled: boolean;
23 23 }
  24 +
24 25 export interface AuthPayload extends SysParamsState {
25 26 authUser: AuthUser;
26 27 userDetails: User;
27 28 forceFullscreen: boolean;
28 29 }
  30 +
29 31 export interface AuthState extends AuthPayload {
30 32 isAuthenticated: boolean;
31 33 isUserLoaded: boolean;
... ...
... ... @@ -295,9 +295,9 @@ export class RuleChainService {
295 295 );
296 296 }
297 297
298   - public getEdgeRuleChains(edgeId: string, pageLink: PageLink, config?:RequestConfig): Observable<PageData<RuleChain>> {
  298 + public getEdgeRuleChains(edgeId: string, pageLink: PageLink, config?: RequestConfig): Observable<PageData<RuleChain>> {
299 299 return this.http.get<PageData<RuleChain>>(`/api/edge/${edgeId}/ruleChains${pageLink.toQuery()}`,
300   - defaultHttpOptionsFromConfig(config) )
  300 + defaultHttpOptionsFromConfig(config));
301 301 }
302 302
303 303 public assignRuleChainToEdge(edgeId: string, ruleChainId: string, config?: RequestConfig): Observable<RuleChain> {
... ...
... ... @@ -26,7 +26,6 @@ import { NULL_UUID } from '@shared/models/id/has-uuid';
26 26 import { ActionNotificationShow } from '@core/notification/notification.actions';
27 27 import { generateSecret, guid } from '@core/utils';
28 28 import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
29   -import { WINDOW } from '@core/services/window.service';
30 29
31 30 @Component({
32 31 selector: 'tb-edge',
... ... @@ -43,15 +42,14 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
43 42 protected translate: TranslateService,
44 43 @Inject('entity') protected entityValue: EdgeInfo,
45 44 @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<EdgeInfo>,
46   - public fb: FormBuilder,
47   - @Inject(WINDOW) protected window: Window) {
  45 + public fb: FormBuilder) {
48 46 super(store, fb, entityValue, entitiesTableConfigValue);
49 47 }
50 48
51 49 ngOnInit() {
52 50 this.edgeScope = this.entitiesTableConfig.componentsData.edgeScope;
53 51 this.entityForm.patchValue({
54   - cloudEndpoint: this.window.location.origin
  52 + cloudEndpoint: window.location.origin
55 53 });
56 54 super.ngOnInit();
57 55 }
... ... @@ -94,7 +92,7 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
94 92 name: entity.name,
95 93 type: entity.type,
96 94 label: entity.label,
97   - cloudEndpoint: entity.cloudEndpoint ? entity.cloudEndpoint : this.window.location.origin,
  95 + cloudEndpoint: entity.cloudEndpoint ? entity.cloudEndpoint : window.location.origin,
98 96 edgeLicenseKey: entity.edgeLicenseKey,
99 97 routingKey: entity.routingKey,
100 98 secret: entity.secret,
... ...
... ... @@ -49,6 +49,7 @@ import { isUndefined } from '@core/utils';
49 49 import { PageLink } from '@shared/models/page/page-link';
50 50 import { Edge } from '@shared/models/edge.models';
51 51 import { mergeMap } from 'rxjs/operators';
  52 +import { PageData } from '@shared/models/page/page-data';
52 53
53 54 @Injectable()
54 55 export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<RuleChain>> {
... ... @@ -83,25 +84,27 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
83 84 }
84 85
85 86 resolve(route: ActivatedRouteSnapshot): EntityTableConfig<RuleChain> {
86   - const routeParams = route.params;
  87 + const edgeId = route.params?.edgeId;
  88 + const ruleChainScope = route.data?.ruleChainsType ? route.data?.ruleChainsType : 'tenant';
87 89 this.config.componentsData = {
88   - ruleChainScope: route.data.ruleChainsType,
89   - edgeId: routeParams.edgeId
  90 + ruleChainScope,
  91 + edgeId
90 92 };
91   - this.config.columns = this.configureEntityTableColumns(this.config.componentsData.ruleChainScope);
92   - this.configureEntityFunctions(this.config.componentsData.ruleChainScope);
93   - this.config.groupActionDescriptors = this.configureGroupActions(this.config.componentsData.ruleChainScope);
94   - this.config.addActionDescriptors = this.configureAddActions(this.config.componentsData.ruleChainScope);
95   - this.config.cellActionDescriptors = this.configureCellActions(this.config.componentsData.ruleChainScope);
96   - if (this.config.componentsData.ruleChainScope === 'tenant' || this.config.componentsData.ruleChainScope === 'edges') {
  93 + this.config.columns = this.configureEntityTableColumns(ruleChainScope);
  94 + this.config.entitiesFetchFunction = this.configureEntityFunctions(ruleChainScope, edgeId);
  95 + this.config.groupActionDescriptors = this.configureGroupActions(ruleChainScope);
  96 + this.config.addActionDescriptors = this.configureAddActions(ruleChainScope);
  97 + this.config.cellActionDescriptors = this.configureCellActions(ruleChainScope);
  98 + if (ruleChainScope === 'tenant' || ruleChainScope === 'edges') {
97 99 this.config.entitySelectionEnabled = ruleChain => ruleChain && !ruleChain.root;
98 100 this.config.deleteEnabled = (ruleChain) => ruleChain && !ruleChain.root;
99 101 this.config.entitiesDeleteEnabled = true;
100   - } else if (this.config.componentsData.ruleChainScope === 'edge') {
101   - this.config.entitySelectionEnabled = ruleChain => this.config.componentsData.edge.rootRuleChainId.id != ruleChain.id.id;
102   - this.edgeService.getEdge(this.config.componentsData.edgeId).subscribe(edge => {
  102 + this.config.tableTitle = this.configureTableTitle(ruleChainScope, null);
  103 + } else if (ruleChainScope === 'edge') {
  104 + this.config.entitySelectionEnabled = ruleChain => this.config.componentsData.edge.rootRuleChainId.id !== ruleChain.id.id;
  105 + this.edgeService.getEdge(edgeId).subscribe(edge => {
103 106 this.config.componentsData.edge = edge;
104   - this.config.tableTitle = edge.name + ': ' + this.translate.instant('edge.rulechains');
  107 + this.config.tableTitle = this.configureTableTitle(ruleChainScope, edge);
105 108 });
106 109 this.config.entitiesDeleteEnabled = false;
107 110 }
... ... @@ -110,24 +113,23 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
110 113
111 114 configureEntityTableColumns(ruleChainScope: string): Array<EntityColumn<RuleChain>> {
112 115 const columns: Array<EntityColumn<RuleChain>> = [];
  116 + columns.push(
  117 + new DateEntityTableColumn<RuleChain>('createdTime', 'common.created-time', this.datePipe, '150px'),
  118 + new EntityTableColumn<RuleChain>('name', 'rulechain.name', '100%')
  119 + );
113 120 if (ruleChainScope === 'tenant' || ruleChainScope === 'edge') {
114 121 columns.push(
115   - new DateEntityTableColumn<RuleChain>('createdTime', 'common.created-time', this.datePipe, '150px'),
116   - new EntityTableColumn<RuleChain>('name', 'rulechain.name', '100%'),
117 122 new EntityTableColumn<RuleChain>('root', 'rulechain.root', '60px',
118 123 entity => {
119 124 if (ruleChainScope === 'edge') {
120   - return checkBoxCell((this.config.componentsData.edge.rootRuleChainId.id == entity.id.id));
  125 + return checkBoxCell((this.config.componentsData.edge.rootRuleChainId.id === entity.id.id));
121 126 } else {
122 127 return checkBoxCell(entity.root);
123 128 }
124 129 })
125 130 );
126   - }
127   - if (ruleChainScope === 'edges') {
  131 + } else if (ruleChainScope === 'edges') {
128 132 columns.push(
129   - new DateEntityTableColumn<RuleChain>('createdTime', 'common.created-time', this.datePipe, '150px'),
130   - new EntityTableColumn<RuleChain>('name', 'rulechain.name', '100%'),
131 133 new EntityTableColumn<RuleChain>('root', 'rulechain.edge-template-root', '60px',
132 134 entity => {
133 135 return checkBoxCell(entity.root);
... ... @@ -157,7 +159,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
157 159 isEnabled: () => true,
158 160 onAction: ($event) => this.importRuleChain($event)
159 161 }
160   - )
  162 + );
161 163 }
162 164 if (ruleChainScope === 'edge') {
163 165 actions.push(
... ... @@ -167,20 +169,28 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
167 169 isEnabled: () => true,
168 170 onAction: ($event) => this.addRuleChainsToEdge($event)
169 171 }
170   - )
  172 + );
171 173 }
172 174 return actions;
173 175 }
174 176
175   - configureEntityFunctions(ruleChainScope: string): void {
  177 + configureEntityFunctions(ruleChainScope: string, edgeId: string): (pageLink) => Observable<PageData<RuleChain>> {
176 178 if (ruleChainScope === 'tenant') {
177   - this.config.tableTitle = this.translate.instant('rulechain.rulechains');
178   - this.config.entitiesFetchFunction = pageLink => this.fetchRuleChains(pageLink);
  179 + return pageLink => this.fetchRuleChains(pageLink);
179 180 } else if (ruleChainScope === 'edges') {
180   - this.config.tableTitle = this.translate.instant('edge.rulechain-templates');
181   - this.config.entitiesFetchFunction = pageLink => this.fetchEdgeRuleChains(pageLink);
  181 + return pageLink => this.fetchEdgeRuleChains(pageLink);
182 182 } else if (ruleChainScope === 'edge') {
183   - this.config.entitiesFetchFunction = pageLink => this.ruleChainService.getEdgeRuleChains(this.config.componentsData.edgeId, pageLink);
  183 + return pageLink => this.ruleChainService.getEdgeRuleChains(edgeId, pageLink);
  184 + }
  185 + }
  186 +
  187 + configureTableTitle(ruleChainScope: string, edge: Edge): string {
  188 + if (ruleChainScope === 'tenant') {
  189 + return this.translate.instant('rulechain.rulechains');
  190 + } else if (ruleChainScope === 'edges') {
  191 + return this.translate.instant('edge.rulechain-templates');
  192 + } else if (ruleChainScope === 'edge') {
  193 + return this.config.tableTitle = edge.name + ': ' + this.translate.instant('edge.rulechains');
184 194 }
185 195 }
186 196
... ... @@ -194,7 +204,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
194 204 isEnabled: true,
195 205 onAction: ($event, entities) => this.unassignRuleChainsFromEdge($event, entities)
196 206 }
197   - )
  207 + );
198 208 }
199 209 return actions;
200 210 }
... ... @@ -215,7 +225,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
215 225 isEnabled: () => true,
216 226 onAction: ($event, entity) => this.exportRuleChain($event, entity)
217 227 }
218   - )
  228 + );
219 229 if (ruleChainScope === 'tenant') {
220 230 actions.push(
221 231 {
... ... @@ -224,7 +234,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
224 234 isEnabled: (entity) => this.isNonRootRuleChain(entity),
225 235 onAction: ($event, entity) => this.setRootRuleChain($event, entity)
226 236 }
227   - )
  237 + );
228 238 }
229 239 if (ruleChainScope === 'edges') {
230 240 actions.push(
... ... @@ -246,7 +256,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
246 256 isEnabled: (entity) => this.isAutoAssignToEdgeRuleChain(entity),
247 257 onAction: ($event, entity) => this.unsetAutoAssignToEdgeRuleChain($event, entity)
248 258 }
249   - )
  259 + );
250 260 }
251 261 }
252 262 if (ruleChainScope === 'edge') {
... ... @@ -260,10 +270,10 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
260 270 {
261 271 name: this.translate.instant('edge.unassign-from-edge'),
262 272 icon: 'assignment_return',
263   - isEnabled: (entity) => entity.id.id != this.config.componentsData.edge.rootRuleChainId.id,
  273 + isEnabled: (entity) => entity.id.id !== this.config.componentsData.edge.rootRuleChainId.id,
264 274 onAction: ($event, entity) => this.unassignFromEdge($event, entity)
265 275 }
266   - )
  276 + );
267 277 }
268 278 return actions;
269 279 }
... ... @@ -298,9 +308,9 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
298 308
299 309 saveRuleChain(ruleChain: RuleChain) {
300 310 if (isUndefined(ruleChain.type)) {
301   - if (this.config.componentsData.ruleChainScope == 'tenant') {
  311 + if (this.config.componentsData.ruleChainScope === 'tenant') {
302 312 ruleChain.type = RuleChainType.CORE;
303   - } else if (this.config.componentsData.ruleChainScope == 'edges') {
  313 + } else if (this.config.componentsData.ruleChainScope === 'edges') {
304 314 ruleChain.type = RuleChainType.EDGE;
305 315 } else {
306 316 // safe fallback to default core type
... ... @@ -335,13 +345,13 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
335 345 this.config.componentsData.edge = edge;
336 346 this.config.table.updateData();
337 347 }
338   - )
  348 + );
339 349 } else {
340 350 this.ruleChainService.setRootRuleChain(ruleChain.id.id).subscribe(
341 351 () => {
342 352 this.config.table.updateData();
343 353 }
344   - )
  354 + );
345 355 }
346 356 }
347 357 }
... ... @@ -415,14 +425,14 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
415 425 this.edgeService.findMissingToRelatedRuleChains(this.config.componentsData.edgeId).subscribe(
416 426 (missingRuleChains) => {
417 427 if (missingRuleChains && Object.keys(missingRuleChains).length > 0) {
418   - let formattedMissingRuleChains: Array<string> = new Array<string>();
  428 + const formattedMissingRuleChains: Array<string> = new Array<string>();
419 429 for (const missingRuleChain of Object.keys(missingRuleChains)) {
420 430 const arrayOfMissingRuleChains = missingRuleChains[missingRuleChain];
421   - const tmp = "- '" + missingRuleChain + "': '" + arrayOfMissingRuleChains.join("', ") + "'";
  431 + const tmp = '- \'' + missingRuleChain + '\': \'' + arrayOfMissingRuleChains.join('\', ') + '\'';
422 432 formattedMissingRuleChains.push(tmp);
423 433 }
424 434 const message = this.translate.instant('edge.missing-related-rule-chains-text',
425   - {missingRuleChains: formattedMissingRuleChains.join("<br>")});
  435 + {missingRuleChains: formattedMissingRuleChains.join('<br>')});
426 436 this.dialogService.alert(this.translate.instant('edge.missing-related-rule-chains-title'),
427 437 message, this.translate.instant('action.close'), true).subscribe(
428 438 () => {
... ... @@ -433,10 +443,10 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
433 443 this.config.table.updateData();
434 444 }
435 445 }
436   - )
  446 + );
437 447 }
438 448 }
439   - )
  449 + );
440 450 }
441 451
442 452 unassignFromEdge($event: Event, ruleChain: RuleChain) {
... ... @@ -505,7 +515,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
505 515 () => {
506 516 this.config.table.updateData();
507 517 }
508   - )
  518 + );
509 519 }
510 520 }
511 521 );
... ... @@ -527,7 +537,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
527 537 () => {
528 538 this.config.table.updateData();
529 539 }
530   - )
  540 + );
531 541 }
532 542 }
533 543 );
... ... @@ -536,7 +546,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
536 546 isNonRootRuleChain(ruleChain: RuleChain) {
537 547 if (this.config.componentsData.ruleChainScope === 'edge') {
538 548 return this.config.componentsData.edge.rootRuleChainId &&
539   - this.config.componentsData.edge.rootRuleChainId.id != ruleChain.id.id;
  549 + this.config.componentsData.edge.rootRuleChainId.id !== ruleChain.id.id;
540 550 }
541 551 return !ruleChain.root;
542 552 }
... ...
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   -md-list.tb-edge-downlinks-table {
17   - padding: 0;
18   -
19   - md-list-item {
20   - padding: 0;
21   - }
22   -
23   - .tb-row {
24   - height: 48px;
25   - padding: 0;
26   - overflow: hidden;
27   -
28   - .tb-cell {
29   - text-overflow: ellipsis;
30   -
31   - &.tb-scroll {
32   - overflow-x: auto;
33   - overflow-y: hidden;
34   - white-space: nowrap;
35   - }
36   -
37   - &.tb-nowrap {
38   - white-space: nowrap;
39   - }
40   - }
41   - }
42   -
43   - .tb-row:hover {
44   - background-color: #eee;
45   - }
46   -
47   - .tb-header:hover {
48   - background: none;
49   - }
50   -
51   - .tb-header {
52   - .tb-cell {
53   - font-size: 12px;
54   - font-weight: 700;
55   - color: rgba(0, 0, 0, .54);
56   - white-space: nowrap;
57   - background: none;
58   - }
59   - }
60   -
61   - .tb-cell {
62   - &:first-child {
63   - padding-left: 14px;
64   - }
65   -
66   - &:last-child {
67   - padding-right: 14px;
68   - }
69   - padding: 0 6px;
70   - margin: auto 0;
71   - overflow: hidden;
72   - font-size: 13px;
73   - color: rgba(0, 0, 0, .87);
74   - text-align: left;
75   - vertical-align: middle;
76   -
77   - .md-button {
78   - padding: 0;
79   - margin: 0;
80   - }
81   - }
82   -
83   - .tb-cell.tb-number {
84   - text-align: right;
85   - }
86   -}
87   -
88   -#tb-edge-downlinks-content {
89   - width: 100%;
90   - min-width: 400px;
91   - height: 100%;
92   - min-height: 50px;
93   -}
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   -import $ from 'jquery';
17   -import 'brace/ext/language_tools';
18   -import 'brace/ext/searchbox';
19   -import 'brace/mode/java';
20   -import 'brace/theme/github';
21   -import beautify from 'js-beautify';
22   -
23   -/* eslint-disable angular/angularelement */
24   -
25   -const js_beautify = beautify.js;
26   -
27   -/*@ngInject*/
28   -export default function EdgeDownlinksContentDialogController($mdDialog, types, content, contentType, title, showingCallback) {
29   -
30   - var vm = this;
31   -
32   - showingCallback.onShowing = function(scope, element) {
33   - updateEditorSize(element);
34   - }
35   -
36   - vm.content = content;
37   - vm.title = title;
38   -
39   - var mode;
40   - if (contentType) {
41   - mode = types.contentType[contentType].code;
42   - if (contentType == types.contentType.JSON.value && vm.content) {
43   - vm.content = js_beautify(vm.content, {indent_size: 4});
44   - }
45   - } else {
46   - mode = 'java';
47   - }
48   -
49   - vm.contentOptions = {
50   - useWrapMode: false,
51   - mode: mode,
52   - showGutter: false,
53   - showPrintMargin: false,
54   - theme: 'github',
55   - advanced: {
56   - enableSnippets: false,
57   - enableBasicAutocompletion: false,
58   - enableLiveAutocompletion: false
59   - },
60   - onLoad: function (_ace) {
61   - vm.editor = _ace;
62   - }
63   - };
64   -
65   - function updateEditorSize(element) {
66   - var newHeight = 400;
67   - var newWidth = 600;
68   - if (vm.content && vm.content.length > 0) {
69   - var lines = vm.content.split('\n');
70   - newHeight = 16 * lines.length + 16;
71   - var maxLineLength = 0;
72   - for (var i = 0; i < lines.length; i++) {
73   - var line = lines[i].replace(/\t/g, ' ').replace(/\n/g, '');
74   - var lineLength = line.length;
75   - maxLineLength = Math.max(maxLineLength, lineLength);
76   - }
77   - newWidth = 8 * maxLineLength + 16;
78   - }
79   - $('#tb-edge-downlinks-content', element).height(newHeight.toString() + "px")
80   - .width(newWidth.toString() + "px");
81   - vm.editor.resize();
82   - }
83   -
84   - vm.close = close;
85   -
86   - function close () {
87   - $mdDialog.hide();
88   - }
89   -
90   -}
91   -
92   -/* eslint-enable angular/angularelement */
1   -<!--
2   -
3   - Copyright © 2016-2020 The Thingsboard Authors
4   -
5   - Licensed under the Apache License, Version 2.0 (the "License");
6   - you may not use this file except in compliance with the License.
7   - You may obtain a copy of the License at
8   -
9   - http://www.apache.org/licenses/LICENSE-2.0
10   -
11   - Unless required by applicable law or agreed to in writing, software
12   - distributed under the License is distributed on an "AS IS" BASIS,
13   - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   - See the License for the specific language governing permissions and
15   - limitations under the License.
16   -
17   --->
18   -<md-dialog aria-label="{{ vm.title | translate }}">
19   - <md-toolbar>
20   - <div class="md-toolbar-tools">
21   - <h2 translate>{{ vm.title }}</h2>
22   - <span flex></span>
23   - <md-button class="md-icon-button" ng-click="vm.close()">
24   - <ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon>
25   - </md-button>
26   - </div>
27   - </md-toolbar>
28   - <md-dialog-content>
29   - <div class="md-dialog-content">
30   - <div flex id="tb-edge-downlinks-content" readonly
31   - ui-ace="vm.contentOptions"
32   - ng-model="vm.content">
33   - </div>
34   - </div>
35   - </md-dialog-content>
36   - <md-dialog-actions layout="row">
37   - <span flex></span>
38   - <md-button ng-disabled="$root.loading" ng-click="vm.close()" style="margin-right:20px;">{{ 'action.close' |
39   - translate }}
40   - </md-button>
41   - </md-dialog-actions>
42   -</md-dialog>
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   -/* eslint-disable import/no-unresolved, import/default */
17   -
18   -import edgeDownlinksHeaderTemplate from './edge-downlinks-header.tpl.html'
19   -
20   -/* eslint-enable import/no-unresolved, import/default */
21   -
22   -/*@ngInject*/
23   -export default function EdgeDownlinksHeaderDirective($compile, $templateCache) {
24   -
25   - var linker = function (scope, element) {
26   -
27   - var template = edgeDownlinksHeaderTemplate;
28   -
29   - element.html($templateCache.get(template));
30   - $compile(element.contents())(scope);
31   - }
32   -
33   - return {
34   - restrict: "A",
35   - replace: false,
36   - link: linker,
37   - scope: false
38   - };
39   -}
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   -/* eslint-disable import/no-unresolved, import/default */
17   -
18   -import edgeDownlinksContentTemplate from './edge-downlinks-content-dialog.tpl.html';
19   -import edgeDownlinlsRowTemplate from './edge-downlinks-row.tpl.html';
20   -
21   -/* eslint-enable import/no-unresolved, import/default */
22   -
23   -/*@ngInject*/
24   -export default function EdgeDownlinksRowDirective($compile, $templateCache, $mdDialog, $document, $translate,
25   - types, utils, toast, entityService, ruleChainService) {
26   -
27   - var linker = function (scope, element, attrs) {
28   -
29   - var template = edgeDownlinlsRowTemplate;
30   -
31   - element.html($templateCache.get(template));
32   - $compile(element.contents())(scope);
33   -
34   - scope.types = types;
35   - scope.downlink = attrs.downlink;
36   -
37   - scope.showEdgeEntityContent = function($event, title, contentType) {
38   - var onShowingCallback = {
39   - onShowing: function(){}
40   - }
41   - if (!contentType) {
42   - contentType = null;
43   - }
44   - var content = '';
45   - switch(scope.downlink.type) {
46   - case types.edgeEventType.relation:
47   - content = angular.toJson(scope.downlink.body);
48   - showDialog();
49   - break;
50   - case types.edgeEventType.ruleChainMetaData:
51   - content = ruleChainService.getRuleChainMetaData(scope.downlink.entityId, {ignoreErrors: true}).then(
52   - function success(info) {
53   - showDialog();
54   - return angular.toJson(info);
55   - }, function fail() {
56   - showError();
57   - });
58   - break;
59   - default:
60   - content = entityService.getEntity(scope.downlink.type, scope.downlink.entityId, {ignoreErrors: true}).then(
61   - function success(info) {
62   - showDialog();
63   - return angular.toJson(info);
64   - }, function fail() {
65   - showError();
66   - });
67   - break;
68   - }
69   - function showDialog() {
70   - $mdDialog.show({
71   - controller: 'EdgeDownlinksContentDialogController',
72   - controllerAs: 'vm',
73   - templateUrl: edgeDownlinksContentTemplate,
74   - locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback},
75   - parent: angular.element($document[0].body),
76   - fullscreen: true,
77   - targetEvent: $event,
78   - multiple: true,
79   - onShowing: function(scope, element) {
80   - onShowingCallback.onShowing(scope, element);
81   - }
82   - });
83   - }
84   - function showError() {
85   - toast.showError($translate.instant('edge.load-entity-error'));
86   - }
87   - }
88   -
89   - scope.checkEdgeDownlinksType = function (type) {
90   - return !(type === types.edgeEventType.widgetType ||
91   - type === types.edgeEventType.adminSettings ||
92   - type === types.edgeEventType.widgetsBundle );
93   - }
94   -
95   - scope.checkTooltip = function($event) {
96   - var el = $event.target;
97   - var $el = angular.element(el);
98   - if(el.offsetWidth < el.scrollWidth && !$el.attr('title')){
99   - $el.attr('title', $el.text());
100   - }
101   - }
102   -
103   - $compile(element.contents())(scope);
104   -
105   - scope.updateStatus = function(downlinkCreatedTime) {
106   - var status;
107   - if (downlinkCreatedTime < scope.queueStartTs) {
108   - status = $translate.instant(types.edgeEventStatus.DEPLOYED.name);
109   - scope.statusColor = types.edgeEventStatus.DEPLOYED.color;
110   - } else {
111   - status = $translate.instant(types.edgeEventStatus.PENDING.name);
112   - scope.statusColor = types.edgeEventStatus.PENDING.color;
113   - }
114   - return status;
115   - }
116   - }
117   -
118   - return {
119   - restrict: "A",
120   - replace: false,
121   - link: linker,
122   - scope: false
123   - };
124   -}
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   -import './downlink.scss';
17   -
18   -/* eslint-disable import/no-unresolved, import/default */
19   -
20   -import edgeDownlinksTableTemplate from './edge-downlinks-table.tpl.html';
21   -
22   -/* eslint-enable import/no-unresolved, import/default */
23   -
24   -/*@ngInject*/
25   -export default function EdgeDownlinksDirective($compile, $templateCache, $rootScope, $translate, types, edgeService, attributeService) {
26   -
27   - var linker = function (scope, element) {
28   -
29   - var template = $templateCache.get(edgeDownlinksTableTemplate);
30   - element.html(template);
31   -
32   - var pageSize = 20;
33   - var startTime = 0;
34   - var endTime = 0;
35   -
36   - scope.timewindow = {
37   - history: {
38   - timewindowMs: 24 * 60 * 60 * 1000 // 1 day
39   - }
40   - }
41   -
42   - scope.topIndex = 0;
43   -
44   - scope.theDownlinks = {
45   - getItemAtIndex: function (index) {
46   - if (index > scope.downlinks.data.length) {
47   - scope.theDownlinks.fetchMoreItems_(index);
48   - return null;
49   - }
50   - var item = scope.downlinks.data[index];
51   - if (item) {
52   - item.indexNumber = index + 1;
53   - }
54   - return item;
55   - },
56   -
57   - getLength: function () {
58   - if (scope.downlinks.hasNext) {
59   - return scope.downlinks.data.length + scope.downlinks.nextPageLink.limit;
60   - } else {
61   - return scope.downlinks.data.length;
62   - }
63   - },
64   -
65   - fetchMoreItems_: function () {
66   - if (scope.downlinks.hasNext && !scope.downlinks.pending) {
67   - if (scope.entityType && scope.entityId && scope.tenantId) {
68   - scope.loadEdgeInfo();
69   - scope.downlinks.pending = true;
70   - edgeService.getEdgeEvents(scope.entityId, scope.downlinks.nextPageLink).then(
71   - function success(downlinks) {
72   - scope.downlinks.data = scope.downlinks.data.concat(prepareEdgeDownlinksData(downlinks.data));
73   - scope.downlinks.nextPageLink = downlinks.nextPageLink;
74   - scope.downlinks.hasNext = downlinks.hasNext;
75   - if (scope.downlinks.hasNext) {
76   - scope.downlinks.nextPageLink.limit = pageSize;
77   - }
78   - scope.downlinks.pending = false;
79   - },
80   - function fail() {
81   - scope.downlinks.hasNext = false;
82   - scope.downlinks.pending = false;
83   - });
84   - } else {
85   - scope.downlinks.hasNext = false;
86   - }
87   - }
88   - }
89   - };
90   -
91   - scope.$watch("entityId", function(newVal, prevVal) {
92   - if (newVal && !angular.equals(newVal, prevVal)) {
93   - scope.resetFilter();
94   - scope.reload();
95   - }
96   - });
97   -
98   - scope.$watch("timewindow", function(newVal, prevVal) {
99   - if (newVal && !angular.equals(newVal, prevVal)) {
100   - scope.reload();
101   - }
102   - }, true);
103   -
104   - scope.resetFilter = function() {
105   - scope.timewindow = {
106   - history: {
107   - timewindowMs: 24 * 60 * 60 * 1000 // 1 day
108   - }
109   - };
110   - }
111   -
112   - scope.updateTimeWindowRange = function() {
113   - if (scope.timewindow.history.timewindowMs) {
114   - var currentTime = (new Date).getTime();
115   - startTime = currentTime - scope.timewindow.history.timewindowMs;
116   - endTime = currentTime;
117   - } else {
118   - startTime = scope.timewindow.history.fixedTimewindow.startTimeMs;
119   - endTime = scope.timewindow.history.fixedTimewindow.endTimeMs;
120   - }
121   - }
122   -
123   - scope.reload = function() {
124   - scope.topIndex = 0;
125   - scope.selected = [];
126   - scope.updateTimeWindowRange();
127   - scope.downlinks = {
128   - data: [],
129   - nextPageLink: {
130   - limit: pageSize,
131   - startTime: startTime,
132   - endTime: endTime
133   - },
134   - hasNext: true,
135   - pending: false
136   - };
137   - scope.theDownlinks.getItemAtIndex(pageSize);
138   - }
139   -
140   - scope.noData = function() {
141   - return scope.downlinks.data.length == 0 && !scope.downlinks.hasNext;
142   - }
143   -
144   - scope.hasData = function() {
145   - return scope.downlinks.data.length > 0;
146   - }
147   -
148   - scope.loading = function() {
149   - return $rootScope.loading;
150   - }
151   -
152   - scope.hasScroll = function() {
153   - var repeatContainer = scope.repeatContainer[0];
154   - if (repeatContainer) {
155   - var scrollElement = repeatContainer.children[0];
156   - if (scrollElement) {
157   - return scrollElement.scrollHeight > scrollElement.clientHeight;
158   - }
159   - }
160   - return false;
161   - }
162   -
163   - scope.subscriptionId = null;
164   -
165   - scope.loadEdgeInfo = function() {
166   - attributeService.getEntityAttributesValues(
167   - scope.entityType,
168   - scope.entityId,
169   - types.attributesScope.server.value,
170   - types.edgeAttributeKeys.queueStartTs,
171   - null).then(
172   - function success(attributes) {
173   - attributes.length > 0 ? scope.onEdgeAttributesUpdate(attributes) : scope.queueStartTs = 0;
174   - });
175   - scope.checkSubscription();
176   - }
177   -
178   - scope.onEdgeAttributesUpdate = function(attributes) {
179   - let edgeAttributes = attributes.reduce(function (map, attribute) {
180   - map[attribute.key] = attribute;
181   - return map;
182   - }, {});
183   - if (edgeAttributes.queueStartTs) {
184   - scope.queueStartTs = edgeAttributes.queueStartTs.lastUpdateTs;
185   - }
186   - }
187   -
188   - scope.checkSubscription = function() {
189   - var newSubscriptionId = null;
190   - if (scope.entityId && scope.entityType && types.attributesScope.server.value) {
191   - newSubscriptionId =
192   - attributeService.subscribeForEntityAttributes(scope.entityType, scope.entityId, types.attributesScope.server.value);
193   - }
194   - if (scope.subscriptionId && scope.subscriptionId != newSubscriptionId) {
195   - attributeService.unsubscribeForEntityAttributes(scope.subscriptionId);
196   - }
197   - scope.subscriptionId = newSubscriptionId;
198   - }
199   -
200   - scope.$on('$destroy', function () {
201   - if (scope.subscriptionId) {
202   - attributeService.unsubscribeForEntityAttributes(scope.subscriptionId);
203   - }
204   - });
205   -
206   - scope.reload();
207   -
208   - $compile(element.contents())(scope);
209   - }
210   - function prepareEdgeDownlinksData(data) {
211   -
212   - data.forEach(
213   - edgeDownlink => {
214   - edgeDownlink.edgeEventActionText = $translate.instant(types.edgeEventActionTypeTranslations[edgeDownlink.action].name);
215   - edgeDownlink.edgeEventTypeText = $translate.instant(types.edgeEventTypeTranslations[edgeDownlink.type].name);
216   - }
217   - );
218   - return data;
219   - }
220   -
221   - return {
222   - restrict: "E",
223   - link: linker,
224   - scope: {
225   - entityType: '=',
226   - entityId: '=',
227   - tenantId: '='
228   - }
229   - };
230   -}
1   -<!--
2   -
3   - Copyright © 2016-2020 The Thingsboard Authors
4   -
5   - Licensed under the Apache License, Version 2.0 (the "License");
6   - you may not use this file except in compliance with the License.
7   - You may obtain a copy of the License at
8   -
9   - http://www.apache.org/licenses/LICENSE-2.0
10   -
11   - Unless required by applicable law or agreed to in writing, software
12   - distributed under the License is distributed on an "AS IS" BASIS,
13   - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   - See the License for the specific language governing permissions and
15   - limitations under the License.
16   -
17   --->
18   -<md-content flex class="md-padding tb-absolute-fill" layout="column">
19   - <section layout="row">
20   - <tb-timewindow flex ng-model="timewindow" history-only as-button="true"></tb-timewindow>
21   - <md-button ng-disabled="$root.loading"
22   - class="md-icon-button" ng-click="reload()">
23   - <md-icon>refresh</md-icon>
24   - <md-tooltip md-direction="top">
25   - {{ 'action.refresh' | translate }}
26   - </md-tooltip>
27   - </md-button>
28   - </section>
29   - <md-list flex layout="column" class="md-whiteframe-z1 tb-edge-downlinks-table">
30   - <md-list class="tb-row tb-header" layout="row" layout-align="start center" tb-edge-downlinks-header>
31   - </md-list>
32   - <md-progress-linear style="max-height: 0px;" md-mode="indeterminate" ng-disabled="!$root.loading"
33   - ng-show="$root.loading"></md-progress-linear>
34   - <md-divider></md-divider>
35   - <span translate layout-align="center center"
36   - style="margin-top: 25px;"
37   - class="tb-prompt" ng-show="noData()">edge.no-downlinks-prompt</span>
38   - <md-virtual-repeat-container ng-show="hasData()" flex md-top-index="topIndex" tb-scope-element="repeatContainer">
39   - <md-list-item md-virtual-repeat="downlink in theDownlinks" md-on-demand flex ng-style="hasScroll() ? {'margin-right':'-15px'} : {}">
40   - <md-list class="tb-row" flex layout="row" layout-align="start center" tb-edge-downlinks-row downlink="{{downlink}}">
41   - </md-list>
42   - <md-divider flex></md-divider>
43   - </md-list-item>
44   - </md-virtual-repeat-container>
45   - </md-list>
46   -</md-content>