Commit a0e74d72054393cc28bb34cd6ecca0b896798715
1 parent
83c2758c
Edge Downlinks new tab implementation 2
Showing
13 changed files
with
784 additions
and
4 deletions
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-event-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 | + * 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 './event-header-edge-event.tpl.html' | ||
19 | + | ||
20 | +/* eslint-enable import/no-unresolved, import/default */ | ||
21 | + | ||
22 | +/*@ngInject*/ | ||
23 | +export default function EventHeaderDirective2($compile, $templateCache, types) { | ||
24 | + | ||
25 | + var linker = function (scope, element, attrs) { | ||
26 | + | ||
27 | + var getTemplate = function(eventType) { | ||
28 | + var template = ''; | ||
29 | + switch(eventType) { | ||
30 | + case types.edgeDownlinks.value: | ||
31 | + template = edgeDownlinksHeaderTemplate; | ||
32 | + break; | ||
33 | + } | ||
34 | + return $templateCache.get(template); | ||
35 | + } | ||
36 | + | ||
37 | + scope.loadTemplate = function() { | ||
38 | + element.html(getTemplate(attrs.eventType)); | ||
39 | + $compile(element.contents())(scope); | ||
40 | + } | ||
41 | + | ||
42 | + attrs.$observe('eventType', function() { | ||
43 | + scope.loadTemplate(); | ||
44 | + }); | ||
45 | + | ||
46 | + } | ||
47 | + | ||
48 | + return { | ||
49 | + restrict: "A", | ||
50 | + replace: false, | ||
51 | + link: linker, | ||
52 | + scope: false | ||
53 | + }; | ||
54 | +} |
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 eventErrorDialogTemplate from './event-content-dialog.tpl.html'; | ||
19 | + | ||
20 | +import edgeDownlinlsRowTemplate from './event-row-edge-event.tpl.html'; | ||
21 | + | ||
22 | +/* eslint-enable import/no-unresolved, import/default */ | ||
23 | + | ||
24 | +/*@ngInject*/ | ||
25 | +export default function EventRowDirective2($compile, $templateCache, $mdDialog, $document, $translate, | ||
26 | + types, utils, toast, entityService, ruleChainService) { | ||
27 | + | ||
28 | + var linker = function (scope, element, attrs) { | ||
29 | + | ||
30 | + var getTemplate = function(eventType) { | ||
31 | + var template = ''; | ||
32 | + switch(eventType) { | ||
33 | + case types.edgeDownlinks.value: | ||
34 | + template = edgeDownlinlsRowTemplate; | ||
35 | + break; | ||
36 | + } | ||
37 | + return $templateCache.get(template); | ||
38 | + } | ||
39 | + | ||
40 | + scope.loadTemplate = function() { | ||
41 | + element.html(getTemplate(attrs.eventType)); | ||
42 | + $compile(element.contents())(scope); | ||
43 | + } | ||
44 | + | ||
45 | + attrs.$observe('eventType', function() { | ||
46 | + scope.loadTemplate(); | ||
47 | + }); | ||
48 | + | ||
49 | + scope.types = types; | ||
50 | + | ||
51 | + scope.event = attrs.event; | ||
52 | + | ||
53 | + scope.showEdgeEntityContent = function($event, title, contentType) { | ||
54 | + var onShowingCallback = { | ||
55 | + onShowing: function(){} | ||
56 | + } | ||
57 | + if (!contentType) { | ||
58 | + contentType = null; | ||
59 | + } | ||
60 | + var content = ''; | ||
61 | + switch(scope.event.type) { | ||
62 | + case types.edgeEventType.relation: | ||
63 | + content = angular.toJson(scope.event.body); | ||
64 | + showDialog(); | ||
65 | + break; | ||
66 | + case types.edgeEventType.ruleChainMetaData: | ||
67 | + content = ruleChainService.getRuleChainMetaData(scope.event.entityId, {ignoreErrors: true}).then( | ||
68 | + function success(info) { | ||
69 | + showDialog(); | ||
70 | + return angular.toJson(info); | ||
71 | + }, function fail() { | ||
72 | + showError(); | ||
73 | + }); | ||
74 | + break; | ||
75 | + default: | ||
76 | + content = entityService.getEntity(scope.event.type, scope.event.entityId, {ignoreErrors: true}).then( | ||
77 | + function success(info) { | ||
78 | + showDialog(); | ||
79 | + return angular.toJson(info); | ||
80 | + }, function fail() { | ||
81 | + showError(); | ||
82 | + }); | ||
83 | + break; | ||
84 | + } | ||
85 | + function showDialog() { | ||
86 | + $mdDialog.show({ | ||
87 | + controller: 'EventContentDialogController2', | ||
88 | + controllerAs: 'vm', | ||
89 | + templateUrl: eventErrorDialogTemplate, | ||
90 | + locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback}, | ||
91 | + parent: angular.element($document[0].body), | ||
92 | + fullscreen: true, | ||
93 | + targetEvent: $event, | ||
94 | + multiple: true, | ||
95 | + onShowing: function(scope, element) { | ||
96 | + onShowingCallback.onShowing(scope, element); | ||
97 | + } | ||
98 | + }); | ||
99 | + } | ||
100 | + function showError() { | ||
101 | + toast.showError($translate.instant('edge.load-entity-error')); | ||
102 | + } | ||
103 | + } | ||
104 | + | ||
105 | + scope.checkEdgeEventType = function (type) { | ||
106 | + return !(type === types.edgeEventType.widgetType || | ||
107 | + type === types.edgeEventType.adminSettings || | ||
108 | + type === types.edgeEventType.widgetsBundle ); | ||
109 | + } | ||
110 | + | ||
111 | + scope.checkTooltip = function($event) { | ||
112 | + var el = $event.target; | ||
113 | + var $el = angular.element(el); | ||
114 | + if(el.offsetWidth < el.scrollWidth && !$el.attr('title')){ | ||
115 | + $el.attr('title', $el.text()); | ||
116 | + } | ||
117 | + } | ||
118 | + | ||
119 | + $compile(element.contents())(scope); | ||
120 | + | ||
121 | + scope.updateStatus = function(eventCreatedTime) { | ||
122 | + var status; | ||
123 | + if (eventCreatedTime < scope.queueStartTs) { | ||
124 | + status = $translate.instant(types.edgeEventStatus.DEPLOYED.name); | ||
125 | + scope.statusColor = types.edgeEventStatus.DEPLOYED.color; | ||
126 | + } else { | ||
127 | + status = $translate.instant(types.edgeEventStatus.PENDING.name); | ||
128 | + scope.statusColor = types.edgeEventStatus.PENDING.color; | ||
129 | + } | ||
130 | + return status; | ||
131 | + } | ||
132 | + } | ||
133 | + | ||
134 | + return { | ||
135 | + restrict: "A", | ||
136 | + replace: false, | ||
137 | + link: linker, | ||
138 | + scope: false | ||
139 | + }; | ||
140 | +} |
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 './event.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 EdgeDownlinksDirective2($compile, $templateCache, $rootScope, $translate, types, | ||
26 | + eventService, edgeService, attributeService) { | ||
27 | + | ||
28 | + var linker = function (scope, element) { | ||
29 | + | ||
30 | + var template = $templateCache.get(edgeDownlinksTableTemplate); | ||
31 | + | ||
32 | + element.html(template); | ||
33 | + | ||
34 | + scope.eventType = types.edgeDownlinks.value; | ||
35 | + | ||
36 | + var pageSize = 20; | ||
37 | + var startTime = 0; | ||
38 | + var endTime = 0; | ||
39 | + | ||
40 | + scope.timewindow = { | ||
41 | + history: { | ||
42 | + timewindowMs: 24 * 60 * 60 * 1000 // 1 day | ||
43 | + } | ||
44 | + } | ||
45 | + | ||
46 | + scope.topIndex = 0; | ||
47 | + | ||
48 | + scope.theEvents = { | ||
49 | + getItemAtIndex: function (index) { | ||
50 | + if (index > scope.events.data.length) { | ||
51 | + scope.theEvents.fetchMoreItems_(index); | ||
52 | + return null; | ||
53 | + } | ||
54 | + var item = scope.events.data[index]; | ||
55 | + if (item) { | ||
56 | + item.indexNumber = index + 1; | ||
57 | + } | ||
58 | + return item; | ||
59 | + }, | ||
60 | + | ||
61 | + getLength: function () { | ||
62 | + if (scope.events.hasNext) { | ||
63 | + return scope.events.data.length + scope.events.nextPageLink.limit; | ||
64 | + } else { | ||
65 | + return scope.events.data.length; | ||
66 | + } | ||
67 | + }, | ||
68 | + | ||
69 | + fetchMoreItems_: function () { | ||
70 | + if (scope.events.hasNext && !scope.events.pending) { | ||
71 | + if (scope.entityType && scope.entityId && scope.eventType && scope.tenantId) { | ||
72 | + scope.loadEdgeInfo(); | ||
73 | + scope.events.pending = true; | ||
74 | + edgeService.getEdgeDownlinks(scope.entityId, scope.events.nextPageLink).then( | ||
75 | + function success(events) { | ||
76 | + scope.events.data = scope.events.data.concat(prepareEdgeEventData(events.data)); | ||
77 | + scope.events.nextPageLink = events.nextPageLink; | ||
78 | + scope.events.hasNext = events.hasNext; | ||
79 | + if (scope.events.hasNext) { | ||
80 | + scope.events.nextPageLink.limit = pageSize; | ||
81 | + } | ||
82 | + scope.events.pending = false; | ||
83 | + }, | ||
84 | + function fail() { | ||
85 | + scope.events.hasNext = false; | ||
86 | + scope.events.pending = false; | ||
87 | + }); | ||
88 | + } else { | ||
89 | + scope.events.hasNext = false; | ||
90 | + } | ||
91 | + } | ||
92 | + } | ||
93 | + }; | ||
94 | + | ||
95 | + scope.$watch("entityId", function(newVal, prevVal) { | ||
96 | + if (newVal && !angular.equals(newVal, prevVal)) { | ||
97 | + scope.resetFilter(); | ||
98 | + scope.reload(); | ||
99 | + } | ||
100 | + }); | ||
101 | + | ||
102 | + scope.$watch("timewindow", function(newVal, prevVal) { | ||
103 | + if (newVal && !angular.equals(newVal, prevVal)) { | ||
104 | + scope.reload(); | ||
105 | + } | ||
106 | + }, true); | ||
107 | + | ||
108 | + scope.resetFilter = function() { | ||
109 | + scope.timewindow = { | ||
110 | + history: { | ||
111 | + timewindowMs: 24 * 60 * 60 * 1000 // 1 day | ||
112 | + } | ||
113 | + }; | ||
114 | + } | ||
115 | + | ||
116 | + scope.updateTimeWindowRange = function() { | ||
117 | + if (scope.timewindow.history.timewindowMs) { | ||
118 | + var currentTime = (new Date).getTime(); | ||
119 | + startTime = currentTime - scope.timewindow.history.timewindowMs; | ||
120 | + endTime = currentTime; | ||
121 | + } else { | ||
122 | + startTime = scope.timewindow.history.fixedTimewindow.startTimeMs; | ||
123 | + endTime = scope.timewindow.history.fixedTimewindow.endTimeMs; | ||
124 | + } | ||
125 | + } | ||
126 | + | ||
127 | + scope.reload = function() { | ||
128 | + scope.topIndex = 0; | ||
129 | + scope.selected = []; | ||
130 | + scope.updateTimeWindowRange(); | ||
131 | + scope.events = { | ||
132 | + data: [], | ||
133 | + nextPageLink: { | ||
134 | + limit: pageSize, | ||
135 | + startTime: startTime, | ||
136 | + endTime: endTime | ||
137 | + }, | ||
138 | + hasNext: true, | ||
139 | + pending: false | ||
140 | + }; | ||
141 | + scope.theEvents.getItemAtIndex(pageSize); | ||
142 | + } | ||
143 | + | ||
144 | + scope.noData = function() { | ||
145 | + return scope.events.data.length == 0 && !scope.events.hasNext; | ||
146 | + } | ||
147 | + | ||
148 | + scope.hasData = function() { | ||
149 | + return scope.events.data.length > 0; | ||
150 | + } | ||
151 | + | ||
152 | + scope.loading = function() { | ||
153 | + return $rootScope.loading; | ||
154 | + } | ||
155 | + | ||
156 | + scope.hasScroll = function() { | ||
157 | + var repeatContainer = scope.repeatContainer[0]; | ||
158 | + if (repeatContainer) { | ||
159 | + var scrollElement = repeatContainer.children[0]; | ||
160 | + if (scrollElement) { | ||
161 | + return scrollElement.scrollHeight > scrollElement.clientHeight; | ||
162 | + } | ||
163 | + } | ||
164 | + return false; | ||
165 | + } | ||
166 | + | ||
167 | + scope.subscriptionId = null; | ||
168 | + | ||
169 | + scope.loadEdgeInfo = function() { | ||
170 | + attributeService.getEntityAttributesValues( | ||
171 | + scope.entityType, | ||
172 | + scope.entityId, | ||
173 | + types.attributesScope.server.value, | ||
174 | + types.edgeAttributeKeys.queueStartTs, | ||
175 | + null).then( | ||
176 | + function success(attributes) { | ||
177 | + attributes.length > 0 ? scope.onEdgeAttributesUpdate(attributes) : scope.queueStartTs = 0; | ||
178 | + }); | ||
179 | + scope.checkSubscription(); | ||
180 | + } | ||
181 | + | ||
182 | + scope.onEdgeAttributesUpdate = function(attributes) { | ||
183 | + let edgeAttributes = attributes.reduce(function (map, attribute) { | ||
184 | + map[attribute.key] = attribute; | ||
185 | + return map; | ||
186 | + }, {}); | ||
187 | + if (edgeAttributes.queueStartTs) { | ||
188 | + scope.queueStartTs = edgeAttributes.queueStartTs.lastUpdateTs; | ||
189 | + } | ||
190 | + } | ||
191 | + | ||
192 | + scope.checkSubscription = function() { | ||
193 | + var newSubscriptionId = null; | ||
194 | + if (scope.entityId && scope.entityType && types.attributesScope.server.value) { | ||
195 | + newSubscriptionId = | ||
196 | + attributeService.subscribeForEntityAttributes(scope.entityType, scope.entityId, types.attributesScope.server.value); | ||
197 | + } | ||
198 | + if (scope.subscriptionId && scope.subscriptionId != newSubscriptionId) { | ||
199 | + attributeService.unsubscribeForEntityAttributes(scope.subscriptionId); | ||
200 | + } | ||
201 | + scope.subscriptionId = newSubscriptionId; | ||
202 | + } | ||
203 | + | ||
204 | + scope.$on('$destroy', function () { | ||
205 | + if (scope.subscriptionId) { | ||
206 | + attributeService.unsubscribeForEntityAttributes(scope.subscriptionId); | ||
207 | + } | ||
208 | + }); | ||
209 | + | ||
210 | + scope.reload(); | ||
211 | + | ||
212 | + $compile(element.contents())(scope); | ||
213 | + } | ||
214 | + function prepareEdgeEventData(data) { | ||
215 | + | ||
216 | + data.forEach( | ||
217 | + edgeEvent => { | ||
218 | + edgeEvent.edgeEventActionText = $translate.instant(types.edgeEventActionType[edgeEvent.action].name); | ||
219 | + edgeEvent.edgeEventTypeText = $translate.instant(types.edgeEventTypeTranslations[edgeEvent.edgeId.entityType].name); | ||
220 | + } | ||
221 | + ); | ||
222 | + return data; | ||
223 | + } | ||
224 | + | ||
225 | + return { | ||
226 | + restrict: "E", | ||
227 | + link: linker, | ||
228 | + scope: { | ||
229 | + entityType: '=', | ||
230 | + entityId: '=', | ||
231 | + tenantId: '=' | ||
232 | + } | ||
233 | + }; | ||
234 | +} |
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 event-type="{{eventType}}"> | ||
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="event in theEvents" 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 event-type="{{eventType}}" event="{{event}}"> | ||
41 | + </md-list> | ||
42 | + <md-divider flex></md-divider> | ||
43 | + </md-list-item> | ||
44 | + </md-virtual-repeat-container> | ||
45 | + </md-list> | ||
46 | +</md-content> |
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-event-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 | + | ||
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 | +<div translate class="tb-cell" flex="20">event.event-time</div> | ||
19 | +<div translate class="tb-cell" flex="10">event.event-type</div> | ||
20 | +<div translate class="tb-cell" flex="15">edge.event-action</div> | ||
21 | +<div translate class="tb-cell" flex="30">edge.entity-id</div> | ||
22 | +<div translate class="tb-cell" flex="15">edge.status</div> | ||
23 | +<div translate class="tb-cell" flex="10">edge.entity-info</div> |
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 | +<div class="tb-cell" flex="20">{{ event.createdTime | date : 'yyyy-MM-dd HH:mm:ss' }}</div> | ||
19 | +<div class="tb-cell" flex="10">{{ event.edgeEventTypeText }}</div> | ||
20 | +<div class="tb-cell" flex="15">{{ event.edgeEventActionText }}</div> | ||
21 | +<div class="tb-cell" flex="30">{{ event.entityId }}</div> | ||
22 | +<div class="tb-cell" flex="15" ng-style="{'color': statusColor}">{{ updateStatus(event.createdTime) }}</div> | ||
23 | +<div class="tb-cell" flex="10"> | ||
24 | + <md-button ng-if="checkEdgeEventType(event.type)" class="md-icon-button md-primary" | ||
25 | + ng-click="showEdgeEntityContent($event, 'edge.entity-info', 'JSON')" | ||
26 | + aria-label="{{ 'action.view' | translate }}"> | ||
27 | + <md-tooltip md-direction="top"> | ||
28 | + {{ 'action.view' | translate }} | ||
29 | + </md-tooltip> | ||
30 | + <md-icon aria-label="{{ 'action.view' | translate }}" | ||
31 | + class="material-icons"> | ||
32 | + more_horiz | ||
33 | + </md-icon> | ||
34 | + </md-button> | ||
35 | +</div> | ||
36 | + | ||
37 | + |
ui/src/app/edge/downlinks/event.scss
0 → 100644
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-event-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-table-2 { | ||
89 | + @extend .tb-event-table; | ||
90 | +} | ||
91 | + | ||
92 | +#tb-event-content { | ||
93 | + width: 100%; | ||
94 | + min-width: 400px; | ||
95 | + height: 100%; | ||
96 | + min-height: 50px; | ||
97 | +} |
@@ -65,11 +65,18 @@ | @@ -65,11 +65,18 @@ | ||
65 | default-event-type="{{vm.types.eventType.error.value}}"> | 65 | default-event-type="{{vm.types.eventType.error.value}}"> |
66 | </tb-event-table> | 66 | </tb-event-table> |
67 | </md-tab> | 67 | </md-tab> |
68 | - <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'edge.downlinks' | translate }}"> | ||
69 | - <tb-edge-downlinks-table flex entity-type="vm.types.entityType.edge" | 68 | + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'edge.edge' | translate }}"> |
69 | + <tb-edge-downlinks-table-old flex entity-type="vm.types.entityType.edge" | ||
70 | entity-id="vm.grid.operatingItem().id.id" | 70 | entity-id="vm.grid.operatingItem().id.id" |
71 | tenant-id="vm.grid.operatingItem().tenantId.id" | 71 | tenant-id="vm.grid.operatingItem().tenantId.id" |
72 | default-event-type="{{vm.types.edgeDownlinks.value}}"> | 72 | default-event-type="{{vm.types.edgeDownlinks.value}}"> |
73 | + </tb-edge-downlinks-table-old> | ||
74 | + </md-tab> | ||
75 | + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'edge.downlinks' | translate }}"> | ||
76 | + <tb-edge-downlinks-table flex entity-type="vm.types.entityType.edge" | ||
77 | + entity-id="vm.grid.operatingItem().id.id" | ||
78 | + tenant-id="vm.grid.operatingItem().tenantId.id" | ||
79 | + default-event-type="{{vm.types.edgeDownlinks.value}}"> | ||
73 | </tb-edge-downlinks-table> | 80 | </tb-edge-downlinks-table> |
74 | </md-tab> | 81 | </md-tab> |
75 | <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'relation.relations' | translate }}"> | 82 | <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'relation.relations' | translate }}"> |
@@ -25,6 +25,10 @@ import AssignEdgeToCustomerController from './assign-to-customer.controller'; | @@ -25,6 +25,10 @@ import AssignEdgeToCustomerController from './assign-to-customer.controller'; | ||
25 | import AddEdgesToCustomerController from './add-edges-to-customer.controller'; | 25 | import AddEdgesToCustomerController from './add-edges-to-customer.controller'; |
26 | import SetRootRuleChainToEdgesController from './set-root-rule-chain-to-edges.controller'; | 26 | import SetRootRuleChainToEdgesController from './set-root-rule-chain-to-edges.controller'; |
27 | import EdgeDirective from './edge.directive'; | 27 | import EdgeDirective from './edge.directive'; |
28 | +import EdgeDownlinksContentDialogController from './downlinks/edge-downlinks-content-dialog.controller'; | ||
29 | +import EdgeDownlinksHeaderDirective from './downlinks/edge-downlinks-header.directive'; | ||
30 | +import EdgeDownlinksRowDirective from './downlinks/edge-downlinks-row.directive'; | ||
31 | +import EdgeDownlinksDirective from "./downlinks/edge-downlinks-table.directive"; | ||
28 | 32 | ||
29 | export default angular.module('thingsboard.edge', [ | 33 | export default angular.module('thingsboard.edge', [ |
30 | uiRouter, | 34 | uiRouter, |
@@ -39,5 +43,9 @@ export default angular.module('thingsboard.edge', [ | @@ -39,5 +43,9 @@ export default angular.module('thingsboard.edge', [ | ||
39 | .controller('AssignEdgeToCustomerController', AssignEdgeToCustomerController) | 43 | .controller('AssignEdgeToCustomerController', AssignEdgeToCustomerController) |
40 | .controller('AddEdgesToCustomerController', AddEdgesToCustomerController) | 44 | .controller('AddEdgesToCustomerController', AddEdgesToCustomerController) |
41 | .controller('SetRootRuleChainToEdgesController', SetRootRuleChainToEdgesController) | 45 | .controller('SetRootRuleChainToEdgesController', SetRootRuleChainToEdgesController) |
46 | + .controller('EdgeDownlinksContentDialogController', EdgeDownlinksContentDialogController) | ||
42 | .directive('tbEdge', EdgeDirective) | 47 | .directive('tbEdge', EdgeDirective) |
48 | + .directive('tbEdgeDownlinksHeader', EdgeDownlinksHeaderDirective) | ||
49 | + .directive('tbEdgeDownlinksRow', EdgeDownlinksRowDirective) | ||
50 | + .directive('tbEdgeDownlinksTable', EdgeDownlinksDirective) | ||
43 | .name; | 51 | .name; |
@@ -26,7 +26,7 @@ | @@ -26,7 +26,7 @@ | ||
26 | </md-tooltip> | 26 | </md-tooltip> |
27 | </md-button> | 27 | </md-button> |
28 | </section> | 28 | </section> |
29 | - <md-list flex layout="column" class="md-whiteframe-z1 tb-edge-downlinks-table"> | 29 | + <md-list flex layout="column" class="md-whiteframe-z1 tb-edge-downlinks-table-old"> |
30 | <md-list class="tb-row tb-header" layout="row" layout-align="start center" tb-event-header event-type="{{eventType}}"> | 30 | <md-list class="tb-row tb-header" layout="row" layout-align="start center" tb-event-header event-type="{{eventType}}"> |
31 | </md-list> | 31 | </md-list> |
32 | <md-progress-linear style="max-height: 0px;" md-mode="indeterminate" ng-disabled="!$root.loading" | 32 | <md-progress-linear style="max-height: 0px;" md-mode="indeterminate" ng-disabled="!$root.loading" |
@@ -28,5 +28,5 @@ export default angular.module('thingsboard.event', [ | @@ -28,5 +28,5 @@ export default angular.module('thingsboard.event', [ | ||
28 | .directive('tbEventHeader', EventHeaderDirective) | 28 | .directive('tbEventHeader', EventHeaderDirective) |
29 | .directive('tbEventRow', EventRowDirective) | 29 | .directive('tbEventRow', EventRowDirective) |
30 | .directive('tbEventTable', EventTableDirective) | 30 | .directive('tbEventTable', EventTableDirective) |
31 | - .directive('tbEdgeDownlinksTable', EdgeDownlinksDirective) | 31 | + .directive('tbEdgeDownlinksTableOld', EdgeDownlinksDirective) |
32 | .name; | 32 | .name; |