add extensions-widget

This commit is contained in:
Sergey Tarnavskiy 2017-12-04 16:51:45 +02:00
parent 32ece471e9
commit 2583cbed40
7 changed files with 240 additions and 17 deletions

View File

@ -21,6 +21,7 @@ import thingsboardLedLight from '../components/led-light.directive';
import thingsboardTimeseriesTableWidget from '../widget/lib/timeseries-table-widget'; import thingsboardTimeseriesTableWidget from '../widget/lib/timeseries-table-widget';
import thingsboardAlarmsTableWidget from '../widget/lib/alarms-table-widget'; import thingsboardAlarmsTableWidget from '../widget/lib/alarms-table-widget';
import thingsboardEntitiesTableWidget from '../widget/lib/entities-table-widget'; import thingsboardEntitiesTableWidget from '../widget/lib/entities-table-widget';
import thingsboardExtensionsTableWidget from '../widget/lib/extensions-table-widget';
import thingsboardRpcWidgets from '../widget/lib/rpc'; import thingsboardRpcWidgets from '../widget/lib/rpc';
@ -42,7 +43,7 @@ import thingsboardTypes from '../common/types.constant';
import thingsboardUtils from '../common/utils.service'; import thingsboardUtils from '../common/utils.service';
export default angular.module('thingsboard.api.widget', ['oc.lazyLoad', thingsboardLedLight, thingsboardTimeseriesTableWidget, export default angular.module('thingsboard.api.widget', ['oc.lazyLoad', thingsboardLedLight, thingsboardTimeseriesTableWidget,
thingsboardAlarmsTableWidget, thingsboardEntitiesTableWidget, thingsboardRpcWidgets, thingsboardTypes, thingsboardUtils]) thingsboardAlarmsTableWidget, thingsboardEntitiesTableWidget, thingsboardExtensionsTableWidget, thingsboardRpcWidgets, thingsboardTypes, thingsboardUtils])
.factory('widgetService', WidgetService) .factory('widgetService', WidgetService)
.name; .name;

View File

@ -34,7 +34,9 @@ export default function ExtensionTableDirective() {
scope: true, scope: true,
bindToController: { bindToController: {
entityId: '=', entityId: '=',
entityType: '@' entityType: '@',
inWidget: '@?',
ctx: '=?'
}, },
controller: ExtensionTableController, controller: ExtensionTableController,
controllerAs: 'vm', controllerAs: 'vm',
@ -70,7 +72,6 @@ function ExtensionTableController($scope, $filter, $document, $translate, types,
vm.reloadExtensions = reloadExtensions; vm.reloadExtensions = reloadExtensions;
vm.updateExtensions = updateExtensions; vm.updateExtensions = updateExtensions;
$scope.$watch("vm.entityId", function(newVal) { $scope.$watch("vm.entityId", function(newVal) {
if (newVal) { if (newVal) {
if ($scope.subscriber) { if ($scope.subscriber) {
@ -92,13 +93,50 @@ function ExtensionTableController($scope, $filter, $document, $translate, types,
} }
}); });
$scope.$watch('vm.selectedExtensions.length', function (newLength) {
var selectionMode = newLength ? true : false;
if (vm.ctx) {
if (selectionMode) {
vm.ctx.hideTitlePanel = true;
$scope.$emit("selectedExtensions", true);
} else if (vm.query.search == null) {
vm.ctx.hideTitlePanel = false;
$scope.$emit("selectedExtensions", false);
}
}
});
$scope.$on("showSearch", function($event, source) {
if(source.entityId == vm.entityId) {
enterFilterMode();
$scope.$emit("filterMode", true);
}
});
$scope.$on("refreshExtensions", function($event, source) {
if(source.entityId == vm.entityId) {
reloadExtensions();
}
});
$scope.$on("addExtension", function($event, source) {
if(source.entityId == vm.entityId) {
addExtension();
}
});
function enterFilterMode() { function enterFilterMode() {
vm.query.search = ''; vm.query.search = '';
if(vm.inWidget) {
vm.ctx.hideTitlePanel = true;
}
} }
function exitFilterMode() { function exitFilterMode() {
vm.query.search = null; vm.query.search = null;
updateExtensions(); updateExtensions();
if(vm.inWidget) {
vm.ctx.hideTitlePanel = false;
$scope.$emit("filterMode", false);
}
} }
function onReorder() { function onReorder() {
@ -256,8 +294,7 @@ function ExtensionTableController($scope, $filter, $document, $translate, types,
vm.extensions = result.slice(startIndex, startIndex + vm.query.limit); vm.extensions = result.slice(startIndex, startIndex + vm.query.limit);
vm.extensionsJSON = angular.toJson(vm.extensions); vm.extensionsJSON = angular.toJson(vm.extensions);
checkForSync() checkForSync();
} }
function subscribeForClientAttributes() { function subscribeForClientAttributes() {
@ -320,7 +357,6 @@ function ExtensionTableController($scope, $filter, $document, $translate, types,
d = d.getFullYear() +'/'+ addZero(d.getMonth()+1) +'/'+ addZero(d.getDate()) + ' ' + addZero(d.getHours()) + ':' + addZero(d.getMinutes()) +':'+ addZero(d.getSeconds()); d = d.getFullYear() +'/'+ addZero(d.getMonth()+1) +'/'+ addZero(d.getDate()) + ' ' + addZero(d.getHours()) + ':' + addZero(d.getMinutes()) +':'+ addZero(d.getSeconds());
return d; return d;
function addZero(num) { function addZero(num) {
if ((angular.isNumber(num) && num < 10) || (angular.isString(num) && num.length === 1)) { if ((angular.isNumber(num) && num < 10) || (angular.isString(num) && num.length === 1)) {
num = '0' + num; num = '0' + num;

View File

@ -20,6 +20,18 @@
min-height: 0; min-height: 0;
} }
.extension-table {
.sync-widget {
max-height: 90px;
overflow: hidden;
}
.toolbar-widget {
min-height: 39px;
max-height: 39px;
}
}
.extension__syncStatus--black { .extension__syncStatus--black {
color: #000000!important; color: #000000!important;
} }

View File

@ -17,9 +17,9 @@
--> -->
<md-content flex class="md-padding tb-absolute-fill tb-data-table extension-table" layout="column"> <md-content flex class="md-padding tb-absolute-fill tb-data-table extension-table" layout="column">
<div layout="column" class="md-whiteframe-z1"> <div layout="column" class="md-whiteframe-z1" ng-class="{'tb-absolute-fill' : vm.inWidget}">
<md-toolbar class="md-table-toolbar md-default" ng-show="!vm.selectedExtensions.length <md-toolbar ng-if="!vm.inWidget" class="md-table-toolbar md-default" ng-show="!vm.selectedExtensions.length
&& vm.query.search === null"> && vm.query.search === null">
<div class="md-toolbar-tools"> <div class="md-toolbar-tools">
<span translate>{{ 'extension.extensions' }}</span> <span translate>{{ 'extension.extensions' }}</span>
<span flex></span> <span flex></span>
@ -44,7 +44,7 @@
</div> </div>
</md-toolbar> </md-toolbar>
<md-toolbar class="md-table-toolbar md-default" ng-show="!vm.selectedExtensions.length <md-toolbar class="md-table-toolbar md-default" ng-show="!vm.selectedExtensions.length
&& vm.query.search != null""> && vm.query.search != null" ng-class="{'toolbar-widget' : vm.inWidget}">
<div class="md-toolbar-tools"> <div class="md-toolbar-tools">
<md-button class="md-icon-button" aria-label="{{ 'action.search' | translate }}"> <md-button class="md-icon-button" aria-label="{{ 'action.search' | translate }}">
<md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">search</md-icon> <md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">search</md-icon>
@ -58,13 +58,13 @@
</md-input-container> </md-input-container>
<md-button class="md-icon-button" aria-label="{{ 'action.back' | translate }}" ng-click="vm.exitFilterMode()"> <md-button class="md-icon-button" aria-label="{{ 'action.back' | translate }}" ng-click="vm.exitFilterMode()">
<md-icon aria-label="{{ 'action.close' | translate }}" class="material-icons">close</md-icon> <md-icon aria-label="{{ 'action.close' | translate }}" class="material-icons">close</md-icon>
<md-tooltip md-direction="top"> <md-tooltip md-direction="{{vm.ctx.dashboard.isWidgetExpanded ? 'bottom' : 'top'}}">
{{ 'action.close' | translate }} {{ 'action.close' | translate }}
</md-tooltip> </md-tooltip>
</md-button> </md-button>
</div> </div>
</md-toolbar> </md-toolbar>
<md-toolbar class="md-table-toolbar alternate" ng-show="vm.selectedExtensions.length"> <md-toolbar class="md-table-toolbar alternate" ng-show="vm.selectedExtensions.length" ng-class="{'toolbar-widget' : vm.inWidget}">
<div class="md-toolbar-tools"> <div class="md-toolbar-tools">
<span translate <span translate
translate-values="{count: vm.selectedExtensions.length}" translate-values="{count: vm.selectedExtensions.length}"
@ -72,14 +72,14 @@
<span flex></span> <span flex></span>
<md-button class="md-icon-button" ng-click="vm.deleteExtensions($event)"> <md-button class="md-icon-button" ng-click="vm.deleteExtensions($event)">
<md-icon>delete</md-icon> <md-icon>delete</md-icon>
<md-tooltip md-direction="top"> <md-tooltip md-direction="{{vm.ctx.dashboard.isWidgetExpanded ? 'bottom' : 'top'}}">
{{ 'action.delete' | translate }} {{ 'action.delete' | translate }}
</md-tooltip> </md-tooltip>
</md-button> </md-button>
</div> </div>
</md-toolbar> </md-toolbar>
<div class="md-padding" flex layout="row"> <div class="md-padding" flex layout="row" ng-class="{'sync-widget' : vm.inWidget}">
<md-input-container flex="50" class="md-block"> <md-input-container flex="50" class="md-block">
<label translate>extension.sync.status</label> <label translate>extension.sync.status</label>
<input ng-model="vm.syncStatus" <input ng-model="vm.syncStatus"
@ -97,7 +97,7 @@
</md-input-container> </md-input-container>
</div> </div>
<md-table-container> <md-table-container flex>
<table md-table md-row-select multiple="" ng-model="vm.selectedExtensions" md-progress="vm.extensionsDeferred.promise"> <table md-table md-row-select multiple="" ng-model="vm.selectedExtensions" md-progress="vm.extensionsDeferred.promise">
<thead md-head md-order="vm.query.order" md-on-reorder="vm.onReorder"> <thead md-head md-order="vm.query.order" md-on-reorder="vm.onReorder">
<tr md-row> <tr md-row>
@ -117,7 +117,7 @@
{{ 'extension.edit' | translate }} {{ 'extension.edit' | translate }}
</md-tooltip> </md-tooltip>
</md-button> </md-button>
<md-button class="md-icon-button" aria-label="{{ 'action.delete' | translate }}" ng-click="vm.deleteExtension($event, extension)"> <!-- add click-function --> <md-button class="md-icon-button" aria-label="{{ 'action.delete' | translate }}" ng-click="vm.deleteExtension($event, extension)">
<md-icon aria-label="{{ 'action.delete' | translate }}" class="material-icons">delete</md-icon> <md-icon aria-label="{{ 'action.delete' | translate }}" class="material-icons">delete</md-icon>
<md-tooltip md-direction="top"> <md-tooltip md-direction="top">
{{ 'extension.delete' | translate }} {{ 'extension.delete' | translate }}
@ -127,11 +127,12 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<md-divider ng-if="vm.inWidget"></md-divider>
</md-table-container> </md-table-container>
<md-table-pagination md-limit="vm.query.limit" md-limit-options="[5, 10, 15]" <md-table-pagination md-limit="vm.query.limit" md-limit-options="[5, 10, 15]"
md-page="vm.query.page" md-total="{{vm.extensionsCount}}" md-page="vm.query.page" md-total="{{vm.extensionsCount}}"
md-on-paginate="vm.onPaginate" md-page-select> md-on-paginate="vm.onPaginate" md-page-select>
</md-table-pagination> </md-table-pagination>
</div> </div>
<div></div> <!-- div for testing values -->
</md-content> </md-content>

View File

@ -0,0 +1,117 @@
/*
* Copyright © 2016-2017 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import './extensions-table-widget.scss';
/* eslint-disable import/no-unresolved, import/default */
import extensionsTableWidgetTemplate from './extensions-table-widget.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
export default angular.module('thingsboard.widgets.extensionsTableWidget', [])
.directive('tbExtensionsTableWidget', ExtensionsTableWidget)
.name;
/*@ngInject*/
function ExtensionsTableWidget() {
return {
restrict: "E",
scope: true,
bindToController: {
ctx: '='
},
controller: ExtensionsTableWidgetController,
controllerAs: 'vm',
templateUrl: extensionsTableWidgetTemplate
};
}
/*@ngInject*/
function ExtensionsTableWidgetController($scope, $translate, utils) {
var vm = this;
vm.datasources = null;
vm.tabsHidden = false;
$scope.$watch('vm.ctx', function() {
if (vm.ctx && vm.ctx.defaultSubscription) {
vm.settings = vm.ctx.settings;
vm.subscription = vm.ctx.defaultSubscription;
vm.datasources = vm.subscription.datasources;
initializeConfig();
updateDatasources();
}
});
function initializeConfig() {
if (vm.settings.extensionsTitle && vm.settings.extensionsTitle.length) {
vm.extensionsTitle = utils.customTranslation(vm.settings.extensionsTitle, vm.settings.extensionsTitle);
} else {
vm.extensionsTitle = $translate.instant('extension.extensions');
}
vm.ctx.widgetTitle = vm.extensionsTitle;
vm.ctx.widgetActions = [vm.addAction, vm.searchAction, vm.refreshAction];
}
function updateDatasources() {
var datasource = vm.datasources[0];
vm.selectedSource = vm.datasources[0];
vm.ctx.widgetTitle = utils.createLabelFromDatasource(datasource, vm.extensionsTitle);
}
vm.changeSelectedSource = function(source) {
vm.selectedSource = source;
}
vm.searchAction = {
name: "action.search",
show: true,
onAction: function() {
$scope.$broadcast("showSearch", vm.selectedSource);
},
icon: "search"
};
vm.refreshAction = {
name: "action.refresh",
show: true,
onAction: function() {
$scope.$broadcast("refreshExtensions", vm.selectedSource);
},
icon: "refresh"
}
vm.addAction = {
name: "action.add",
show: true,
onAction: function() {
$scope.$broadcast("addExtension", vm.selectedSource);
},
icon: "add"
}
$scope.$on("filterMode", function($event, mode) {
vm.tabsHidden = mode;
});
$scope.$on("selectedExtensions", function($event, mode) {
vm.tabsHidden = mode;
});
}

View File

@ -0,0 +1,29 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
tb-extension-table {
md-content {
background-color: #fff;
}
}
md-tabs.hide-tabs-menu {
md-tabs-wrapper {
display: none;
}
md-tabs-content-wrapper {
top: 0 !important;
}
}

View File

@ -0,0 +1,27 @@
<!--
Copyright © 2016-2017 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<md-tabs id="tabs" md-border-bottom flex class="tb-absolute-fill" ng-class="{'hide-tabs-menu': vm.datasources.length == 1 || vm.tabsHidden}">
<md-tab ng-repeat="source in vm.datasources" label="{{ source.name }}" md-on-select="vm.changeSelectedSource(source)">
<tb-extension-table flex
entity-id="source.entityId"
entity-type="{{source.entityType}}"
in-widget="true"
ctx="vm.ctx">
</tb-extension-table>
</md-tab>
</md-tabs>