Commit c3e62a7b166962ab15a29423938cbfdae6f300c6
Merge branch 'master' of github.com:thingsboard/thingsboard
Showing
6 changed files
with
187 additions
and
33 deletions
ui/src/app/entity/relation/relation-dialog.controller.js
renamed from
ui/src/app/entity/relation/add-relation-dialog.controller.js
... | ... | @@ -13,42 +13,113 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | + | |
17 | +import 'brace/ext/language_tools'; | |
18 | +import 'brace/mode/json'; | |
19 | +import 'brace/theme/github'; | |
20 | +import beautify from 'js-beautify'; | |
21 | + | |
22 | +import './relation-dialog.scss'; | |
23 | + | |
24 | +const js_beautify = beautify.js; | |
25 | + | |
16 | 26 | /*@ngInject*/ |
17 | -export default function AddRelationDialogController($scope, $mdDialog, types, entityRelationService, direction, entityId) { | |
27 | +export default function RelationDialogController($scope, $mdDialog, types, entityRelationService, isAdd, direction, relation, showingCallback) { | |
18 | 28 | |
19 | 29 | var vm = this; |
20 | 30 | |
21 | 31 | vm.types = types; |
32 | + vm.isAdd = isAdd; | |
22 | 33 | vm.direction = direction; |
23 | - vm.targetEntityId = {}; | |
24 | 34 | |
25 | - vm.relation = {}; | |
26 | - if (vm.direction == vm.types.entitySearchDirection.from) { | |
27 | - vm.relation.from = entityId; | |
35 | + showingCallback.onShowing = function(scope, element) { | |
36 | + updateEditorSize(element); | |
37 | + } | |
38 | + | |
39 | + vm.relationAdditionalInfoOptions = { | |
40 | + useWrapMode: false, | |
41 | + mode: 'json', | |
42 | + showGutter: false, | |
43 | + showPrintMargin: false, | |
44 | + theme: 'github', | |
45 | + advanced: { | |
46 | + enableSnippets: false, | |
47 | + enableBasicAutocompletion: false, | |
48 | + enableLiveAutocompletion: false | |
49 | + }, | |
50 | + onLoad: function (_ace) { | |
51 | + vm.editor = _ace; | |
52 | + } | |
53 | + }; | |
54 | + | |
55 | + vm.relation = relation; | |
56 | + if (vm.isAdd) { | |
57 | + vm.relation.type = types.entityRelationType.contains; | |
58 | + vm.targetEntityId = {}; | |
28 | 59 | } else { |
29 | - vm.relation.to = entityId; | |
60 | + if (vm.direction == vm.types.entitySearchDirection.from) { | |
61 | + vm.targetEntityId = vm.relation.to; | |
62 | + } else { | |
63 | + vm.targetEntityId = vm.relation.from; | |
64 | + } | |
30 | 65 | } |
31 | - vm.relation.type = types.entityRelationType.contains; | |
32 | 66 | |
33 | - vm.add = add; | |
67 | + vm.save = save; | |
34 | 68 | vm.cancel = cancel; |
35 | 69 | |
70 | + vm.additionalInfo = ''; | |
71 | + | |
72 | + if (vm.relation.additionalInfo) { | |
73 | + vm.additionalInfo = angular.toJson(vm.relation.additionalInfo); | |
74 | + vm.additionalInfo = js_beautify(vm.additionalInfo, {indent_size: 4}); | |
75 | + } | |
76 | + | |
77 | + $scope.$watch('vm.additionalInfo', () => { | |
78 | + $scope.theForm.$setValidity("additionalInfo", true); | |
79 | + }); | |
80 | + | |
81 | + function updateEditorSize(element) { | |
82 | + var newWidth = 600; | |
83 | + var newHeight = 200; | |
84 | + angular.element('#tb-relation-additional-info', element).height(newHeight.toString() + "px") | |
85 | + .width(newWidth.toString() + "px"); | |
86 | + vm.editor.resize(); | |
87 | + } | |
88 | + | |
36 | 89 | function cancel() { |
37 | 90 | $mdDialog.cancel(); |
38 | 91 | } |
39 | 92 | |
40 | - function add() { | |
41 | - if (vm.direction == vm.types.entitySearchDirection.from) { | |
42 | - vm.relation.to = vm.targetEntityId; | |
43 | - } else { | |
44 | - vm.relation.from = vm.targetEntityId; | |
93 | + function save() { | |
94 | + if (vm.isAdd) { | |
95 | + if (vm.direction == vm.types.entitySearchDirection.from) { | |
96 | + vm.relation.to = vm.targetEntityId; | |
97 | + } else { | |
98 | + vm.relation.from = vm.targetEntityId; | |
99 | + } | |
45 | 100 | } |
46 | 101 | $scope.theForm.$setPristine(); |
47 | - entityRelationService.saveRelation(vm.relation).then( | |
48 | - function success() { | |
49 | - $mdDialog.hide(); | |
102 | + | |
103 | + var valid = true; | |
104 | + if (vm.additionalInfo && vm.additionalInfo.length) { | |
105 | + try { | |
106 | + vm.relation.additionalInfo = angular.fromJson(vm.additionalInfo); | |
107 | + } catch(e) { | |
108 | + valid = false; | |
50 | 109 | } |
51 | - ); | |
110 | + } else { | |
111 | + vm.relation.additionalInfo = null; | |
112 | + } | |
113 | + | |
114 | + $scope.theForm.$setValidity("additionalInfo", valid); | |
115 | + | |
116 | + if (valid) { | |
117 | + entityRelationService.saveRelation(vm.relation).then( | |
118 | + function success() { | |
119 | + $mdDialog.hide(); | |
120 | + } | |
121 | + ); | |
122 | + } | |
52 | 123 | } |
53 | 124 | |
54 | 125 | } | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2017 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 | +.tb-relation-additional-info-panel { | |
18 | + margin-left: 15px; | |
19 | + border: 1px solid #C0C0C0; | |
20 | + height: 100%; | |
21 | + #tb-relation-additional-info { | |
22 | + min-width: 600px; | |
23 | + min-height: 200px; | |
24 | + width: 100%; | |
25 | + height: 100%; | |
26 | + } | |
27 | +} | ... | ... |
ui/src/app/entity/relation/relation-dialog.tpl.html
renamed from
ui/src/app/entity/relation/add-relation-dialog.tpl.html
... | ... | @@ -15,11 +15,11 @@ |
15 | 15 | limitations under the License. |
16 | 16 | |
17 | 17 | --> |
18 | -<md-dialog aria-label="{{ 'relation.add' | translate }}" style="min-width: 400px;"> | |
19 | - <form name="theForm" ng-submit="vm.add()"> | |
18 | +<md-dialog aria-label="{{ (vm.isAdd ? 'relation.add' : 'relation.edit' ) | translate }}" style="min-width: 400px;"> | |
19 | + <form name="theForm" ng-submit="vm.save()"> | |
20 | 20 | <md-toolbar> |
21 | 21 | <div class="md-toolbar-tools"> |
22 | - <h2 translate>relation.add</h2> | |
22 | + <h2 translate>{{ vm.isAdd ? 'relation.add' : 'relation.edit'}}</h2> | |
23 | 23 | <span flex></span> |
24 | 24 | <md-button class="md-icon-button" ng-click="vm.cancel()"> |
25 | 25 | <ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon> |
... | ... | @@ -32,17 +32,29 @@ |
32 | 32 | <div class="md-dialog-content"> |
33 | 33 | <md-content class="md-padding" layout="column"> |
34 | 34 | <fieldset ng-disabled="loading"> |
35 | - <tb-relation-type-autocomplete ng-model="vm.relation.type" | |
35 | + <tb-relation-type-autocomplete ng-disabled="!vm.isAdd" | |
36 | + ng-model="vm.relation.type" | |
36 | 37 | tb-required="true" |
37 | 38 | ng-disabled="loading"> |
38 | 39 | </tb-relation-type-autocomplete> |
39 | 40 | <small>{{(vm.direction == vm.types.entitySearchDirection.from ? |
40 | 41 | 'relation.to-entity' : 'relation.from-entity') | translate}}</small> |
41 | 42 | <tb-entity-select flex |
43 | + ng-disabled="!vm.isAdd" | |
42 | 44 | the-form="theForm" |
43 | 45 | tb-required="true" |
44 | 46 | ng-model="vm.targetEntityId"> |
45 | 47 | </tb-entity-select> |
48 | + <div class="md-caption" style="padding-left: 3px; padding-bottom: 10px; color: rgba(0,0,0,0.57);" translate>relation.additional-info</div> | |
49 | + <div flex class="tb-relation-additional-info-panel" layout="column"> | |
50 | + <div flex id="tb-relation-additional-info" | |
51 | + ui-ace="vm.relationAdditionalInfoOptions" | |
52 | + ng-model="vm.additionalInfo"> | |
53 | + </div> | |
54 | + </div> | |
55 | + <div class="tb-error-messages" ng-messages="theForm.$error" role="alert"> | |
56 | + <div translate ng-message="additionalInfo" class="tb-error-message">relation.invalid-additional-info</div> | |
57 | + </div> | |
46 | 58 | </fieldset> |
47 | 59 | </md-content> |
48 | 60 | </div> |
... | ... | @@ -51,7 +63,7 @@ |
51 | 63 | <span flex></span> |
52 | 64 | <md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit" |
53 | 65 | class="md-raised md-primary"> |
54 | - {{ 'action.add' | translate }} | |
66 | + {{ (vm.isAdd ? 'action.add' : 'action.save') | translate }} | |
55 | 67 | </md-button> |
56 | 68 | <md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | |
57 | 69 | translate }} | ... | ... |
... | ... | @@ -19,11 +19,11 @@ import './relation-table.scss'; |
19 | 19 | /* eslint-disable import/no-unresolved, import/default */ |
20 | 20 | |
21 | 21 | import relationTableTemplate from './relation-table.tpl.html'; |
22 | -import addRelationTemplate from './add-relation-dialog.tpl.html'; | |
22 | +import relationTemplate from './relation-dialog.tpl.html'; | |
23 | 23 | |
24 | 24 | /* eslint-enable import/no-unresolved, import/default */ |
25 | 25 | |
26 | -import AddRelationController from './add-relation-dialog.controller'; | |
26 | +import RelationController from './relation-dialog.controller'; | |
27 | 27 | |
28 | 28 | /*@ngInject*/ |
29 | 29 | export default function RelationTable() { |
... | ... | @@ -66,6 +66,7 @@ function RelationTableController($scope, $q, $mdDialog, $document, $translate, $ |
66 | 66 | vm.onReorder = onReorder; |
67 | 67 | vm.onPaginate = onPaginate; |
68 | 68 | vm.addRelation = addRelation; |
69 | + vm.editRelation = editRelation; | |
69 | 70 | vm.deleteRelation = deleteRelation; |
70 | 71 | vm.deleteRelations = deleteRelations; |
71 | 72 | vm.reloadRelations = reloadRelations; |
... | ... | @@ -110,18 +111,52 @@ function RelationTableController($scope, $q, $mdDialog, $document, $translate, $ |
110 | 111 | if ($event) { |
111 | 112 | $event.stopPropagation(); |
112 | 113 | } |
113 | - var entityId = { | |
114 | - id: vm.entityId, | |
115 | - entityType: vm.entityType | |
116 | - }; | |
114 | + openRelationDialog($event); | |
115 | + } | |
116 | + | |
117 | + function editRelation($event, relation) { | |
118 | + if ($event) { | |
119 | + $event.stopPropagation(); | |
120 | + } | |
121 | + openRelationDialog($event, relation); | |
122 | + } | |
123 | + | |
124 | + function openRelationDialog($event, relation) { | |
125 | + if ($event) { | |
126 | + $event.stopPropagation(); | |
127 | + } | |
128 | + var isAdd = false; | |
129 | + if (!relation) { | |
130 | + isAdd = true; | |
131 | + var entityId = { | |
132 | + id: vm.entityId, | |
133 | + entityType: vm.entityType | |
134 | + }; | |
135 | + relation = {}; | |
136 | + if (vm.direction == vm.types.entitySearchDirection.from) { | |
137 | + relation.from = entityId; | |
138 | + } else { | |
139 | + relation.to = entityId; | |
140 | + } | |
141 | + } | |
142 | + var onShowingCallback = { | |
143 | + onShowing: function(){} | |
144 | + } | |
117 | 145 | $mdDialog.show({ |
118 | - controller: AddRelationController, | |
146 | + controller: RelationController, | |
119 | 147 | controllerAs: 'vm', |
120 | - templateUrl: addRelationTemplate, | |
148 | + templateUrl: relationTemplate, | |
121 | 149 | parent: angular.element($document[0].body), |
122 | - locals: { direction: vm.direction, entityId: entityId }, | |
150 | + locals: { isAdd: isAdd, | |
151 | + direction: vm.direction, | |
152 | + relation: relation, | |
153 | + showingCallback: onShowingCallback}, | |
154 | + targetEvent: $event, | |
123 | 155 | fullscreen: true, |
124 | - targetEvent: $event | |
156 | + skipHide: true, | |
157 | + onShowing: function(scope, element) { | |
158 | + onShowingCallback.onShowing(scope, element); | |
159 | + } | |
125 | 160 | }).then(function () { |
126 | 161 | reloadRelations(); |
127 | 162 | }, function () { | ... | ... |
... | ... | @@ -112,6 +112,12 @@ |
112 | 112 | <td md-cell ng-if="vm.direction == vm.types.entitySearchDirection.from">{{ relation.toName }}</td> |
113 | 113 | <td md-cell ng-if="vm.direction == vm.types.entitySearchDirection.to">{{ relation.fromName }}</td> |
114 | 114 | <td md-cell class="tb-action-cell"> |
115 | + <md-button class="md-icon-button" aria-label="{{ 'action.edit' | translate }}" ng-click="vm.editRelation($event, relation)"> | |
116 | + <md-icon aria-label="{{ 'action.edit' | translate }}" class="material-icons">edit</md-icon> | |
117 | + <md-tooltip md-direction="top"> | |
118 | + {{ 'relation.edit' | translate }} | |
119 | + </md-tooltip> | |
120 | + </md-button> | |
115 | 121 | <md-button class="md-icon-button" aria-label="{{ 'action.delete' | translate }}" ng-click="vm.deleteRelation($event, relation)"> |
116 | 122 | <md-icon aria-label="{{ 'action.delete' | translate }}" class="material-icons">delete</md-icon> |
117 | 123 | <md-tooltip md-direction="top"> | ... | ... |
... | ... | @@ -888,6 +888,7 @@ export default angular.module('thingsboard.locale', []) |
888 | 888 | "relation-type-required": "Relation type is required.", |
889 | 889 | "any-relation-type": "Any type", |
890 | 890 | "add": "Add relation", |
891 | + "edit": "Edit relation", | |
891 | 892 | "delete-to-relation-title": "Are you sure you want to delete relation to the entity '{{entityName}}'?", |
892 | 893 | "delete-to-relation-text": "Be careful, after the confirmation the entity '{{entityName}}' will be unrelated from the current entity.", |
893 | 894 | "delete-to-relations-title": "Are you sure you want to delete { count, select, 1 {1 relation} other {# relations} }?", |
... | ... | @@ -899,7 +900,9 @@ export default angular.module('thingsboard.locale', []) |
899 | 900 | "remove-relation-filter": "Remove relation filter", |
900 | 901 | "add-relation-filter": "Add relation filter", |
901 | 902 | "any-relation": "Any relation", |
902 | - "relation-filters": "Relation filters" | |
903 | + "relation-filters": "Relation filters", | |
904 | + "additional-info": "Additional info (JSON)", | |
905 | + "invalid-additional-info": "Unable to parse additional info json." | |
903 | 906 | }, |
904 | 907 | "rule": { |
905 | 908 | "rule": "Rule", | ... | ... |