Browse Source

UI: Improve dashboard toolbar. Implement entity copy function.

pull/154/head
Igor Kulikov 9 years ago
parent
commit
ffc7a57e59
  1. 29
      ui/src/app/api/entity.service.js
  2. 1
      ui/src/app/common/dashboard-utils.service.js
  3. 51
      ui/src/app/components/expand-fullscreen.directive.js
  4. 4
      ui/src/app/dashboard/dashboard-settings.controller.js
  5. 3
      ui/src/app/dashboard/dashboard-settings.tpl.html
  6. 88
      ui/src/app/dashboard/dashboard-toolbar.directive.js
  7. 114
      ui/src/app/dashboard/dashboard-toolbar.scss
  8. 35
      ui/src/app/dashboard/dashboard-toolbar.tpl.html
  9. 17
      ui/src/app/dashboard/dashboard.controller.js
  10. 80
      ui/src/app/dashboard/dashboard.scss
  11. 190
      ui/src/app/dashboard/dashboard.tpl.html
  12. 2
      ui/src/app/dashboard/index.js
  13. 1
      ui/src/app/locale/locale.constant.js
  14. 2
      ui/src/scss/constants.scss

29
ui/src/app/api/entity.service.js

@ -36,7 +36,8 @@ function EntityService($http, $q, $filter, $translate, userService, deviceServic
saveRelatedEntity: saveRelatedEntity, saveRelatedEntity: saveRelatedEntity,
getRelatedEntity: getRelatedEntity, getRelatedEntity: getRelatedEntity,
deleteRelatedEntity: deleteRelatedEntity, deleteRelatedEntity: deleteRelatedEntity,
moveEntity: moveEntity moveEntity: moveEntity,
copyEntity: copyEntity
}; };
return service; return service;
@ -626,6 +627,32 @@ function EntityService($http, $q, $filter, $translate, userService, deviceServic
return deferred.promise; return deferred.promise;
} }
function copyEntity(entity, targetParentId, keys) {
var deferred = $q.defer();
if (!entity.id && !entity.id.id) {
deferred.reject();
} else {
getRelatedEntity(entity.id, keys).then(
function success(relatedEntity) {
delete relatedEntity.id.id;
relatedEntity.name = entity.name;
saveRelatedEntity(relatedEntity, targetParentId, keys).then(
function success(savedEntity) {
deferred.resolve(savedEntity);
},
function fail() {
deferred.reject();
}
);
},
function fail() {
deferred.reject();
}
);
}
return deferred.promise;
}
function saveEntityPromise(entity) { function saveEntityPromise(entity) {
var entityType = entity.id.entityType; var entityType = entity.id.entityType;
if (!entity.id.id) { if (!entity.id.id) {

1
ui/src/app/common/dashboard-utils.service.js

@ -179,6 +179,7 @@ function DashboardUtils(types, utils, timeService) {
dashboard.configuration.settings.showEntitiesSelect = true; dashboard.configuration.settings.showEntitiesSelect = true;
dashboard.configuration.settings.showDashboardTimewindow = true; dashboard.configuration.settings.showDashboardTimewindow = true;
dashboard.configuration.settings.showDashboardExport = true; dashboard.configuration.settings.showDashboardExport = true;
dashboard.configuration.settings.toolbarAlwaysOpen = false;
} else { } else {
if (angular.isUndefined(dashboard.configuration.settings.stateControllerId)) { if (angular.isUndefined(dashboard.configuration.settings.stateControllerId)) {
dashboard.configuration.settings.stateControllerId = 'default'; dashboard.configuration.settings.stateControllerId = 'default';

51
ui/src/app/components/expand-fullscreen.directive.js

@ -24,7 +24,7 @@ export default angular.module('thingsboard.directives.expandFullscreen', [])
/* eslint-disable angular/angularelement */ /* eslint-disable angular/angularelement */
/*@ngInject*/ /*@ngInject*/
function ExpandFullscreen($compile, $document) { function ExpandFullscreen($compile, $document, $timeout) {
var uniqueId = 1; var uniqueId = 1;
var linker = function (scope, element, attrs) { var linker = function (scope, element, attrs) {
@ -97,10 +97,6 @@ function ExpandFullscreen($compile, $document) {
scope.expanded = !scope.expanded; scope.expanded = !scope.expanded;
} }
var expandButton = null;
if (attrs.expandButtonId) {
expandButton = $('#' + attrs.expandButtonId, element)[0];
}
var buttonSize; var buttonSize;
if (attrs.expandButtonSize) { if (attrs.expandButtonSize) {
buttonSize = attrs.expandButtonSize; buttonSize = attrs.expandButtonSize;
@ -115,27 +111,38 @@ function ExpandFullscreen($compile, $document) {
'options=\'{"easing": "circ-in-out", "duration": 375, "rotation": "none"}\'>' + 'options=\'{"easing": "circ-in-out", "duration": 375, "rotation": "none"}\'>' +
'</ng-md-icon>'; '</ng-md-icon>';
if (expandButton) { if (attrs.expandButtonId) {
expandButton = angular.element(expandButton); $timeout(function() {
if (scope.hideExpandButton()) { var expandButton = $('#' + attrs.expandButtonId, element)[0];
expandButton.remove(); renderExpandButton(expandButton);
} else { });
expandButton.attr('md-ink-ripple', 'false'); } else {
expandButton.append(html); renderExpandButton();
}
function renderExpandButton(expandButton) {
if (expandButton) {
expandButton = angular.element(expandButton);
if (scope.hideExpandButton()) {
expandButton.remove();
} else {
expandButton.attr('md-ink-ripple', 'false');
expandButton.append(html);
$compile(expandButton.contents())(scope); $compile(expandButton.contents())(scope);
expandButton.on("click", scope.toggleExpand); expandButton.on("click", scope.toggleExpand);
} }
} else if (!scope.hideExpandButton()) { } else if (!scope.hideExpandButton()) {
var button = angular.element('<md-button class="tb-fullscreen-button-style tb-fullscreen-button-pos md-icon-button" ' + var button = angular.element('<md-button class="tb-fullscreen-button-style tb-fullscreen-button-pos md-icon-button" ' +
'md-ink-ripple="false" ng-click="toggleExpand($event)">' + 'md-ink-ripple="false" ng-click="toggleExpand($event)">' +
html + html +
'</md-button>'); '</md-button>');
$compile(button)(scope); $compile(button)(scope);
element.prepend(button); element.prepend(button);
}
} }
} }

4
ui/src/app/dashboard/dashboard-settings.controller.js

@ -57,6 +57,10 @@ export default function DashboardSettingsController($scope, $mdDialog, statesCon
if (angular.isUndefined(vm.settings.showDashboardExport)) { if (angular.isUndefined(vm.settings.showDashboardExport)) {
vm.settings.showDashboardExport = true; vm.settings.showDashboardExport = true;
} }
if (angular.isUndefined(vm.settings.toolbarAlwaysOpen)) {
vm.settings.toolbarAlwaysOpen = false;
}
} }
if (vm.gridSettings) { if (vm.gridSettings) {

3
ui/src/app/dashboard/dashboard-settings.tpl.html

@ -41,6 +41,9 @@
</md-select> </md-select>
</md-input-container> </md-input-container>
<div layout="row" layout-align="start center"> <div layout="row" layout-align="start center">
<md-checkbox flex aria-label="{{ 'dashboard.toolbar-always-open' | translate }}"
ng-model="vm.settings.toolbarAlwaysOpen">{{ 'dashboard.toolbar-always-open' | translate }}
</md-checkbox>
<md-checkbox flex aria-label="{{ 'dashboard.display-title' | translate }}" <md-checkbox flex aria-label="{{ 'dashboard.display-title' | translate }}"
ng-model="vm.settings.showTitle">{{ 'dashboard.display-title' | translate }} ng-model="vm.settings.showTitle">{{ 'dashboard.display-title' | translate }}
</md-checkbox> </md-checkbox>

88
ui/src/app/dashboard/dashboard-toolbar.directive.js

@ -0,0 +1,88 @@
/*
* 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 './dashboard-toolbar.scss';
import 'javascript-detect-element-resize/detect-element-resize';
/* eslint-disable import/no-unresolved, import/default */
import dashboardToolbarTemplate from './dashboard-toolbar.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
export default function DashboardToolbar() {
return {
restrict: "E",
scope: true,
transclude: true,
bindToController: {
toolbarOpened: '=',
forceFullscreen: '=',
onTriggerClick: '&'
},
controller: DashboardToolbarController,
controllerAs: 'vm',
templateUrl: dashboardToolbarTemplate
};
}
/* eslint-disable angular/angularelement */
/*@ngInject*/
function DashboardToolbarController($scope, $element, $timeout, mdFabToolbarAnimation) {
let vm = this;
vm.mdFabToolbarElement = angular.element($element[0].querySelector('md-fab-toolbar'));
$timeout(function() {
vm.mdFabBackgroundElement = angular.element(vm.mdFabToolbarElement[0].querySelector('.md-fab-toolbar-background'));
vm.mdFabTriggerElement = angular.element(vm.mdFabToolbarElement[0].querySelector('md-fab-trigger button'));
});
addResizeListener(vm.mdFabToolbarElement[0], triggerFabResize); // eslint-disable-line no-undef
$scope.$on("$destroy", function () {
removeResizeListener(vm.mdFabToolbarElement[0], triggerFabResize); // eslint-disable-line no-undef
});
function triggerFabResize() {
var ctrl = vm.mdFabToolbarElement.controller('mdFabToolbar');
if (ctrl.isOpen) {
if (!vm.mdFabBackgroundElement[0].offsetWidth) {
mdFabToolbarAnimation.addClass(vm.mdFabToolbarElement, 'md-is-open', function () {
});
} else {
var color = window.getComputedStyle(vm.mdFabTriggerElement[0]).getPropertyValue('background-color'); //eslint-disable-line
var width = vm.mdFabToolbarElement[0].offsetWidth;
var scale = 2 * (width / vm.mdFabTriggerElement[0].offsetWidth);
vm.mdFabBackgroundElement[0].style.backgroundColor = color;
vm.mdFabBackgroundElement[0].style.borderRadius = width + 'px';
var transform = vm.mdFabBackgroundElement[0].style.transform;
var targetTransform = 'scale(' + scale + ')';
if (!transform || !angular.equals(transform, targetTransform)) {
vm.mdFabBackgroundElement[0].style.transform = targetTransform;
}
}
}
}
}

114
ui/src/app/dashboard/dashboard-toolbar.scss

@ -0,0 +1,114 @@
/**
* 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 "~compass-sass-mixins/lib/compass";
@import '../../scss/constants';
tb-dashboard-toolbar {
md-fab-toolbar {
&.md-is-open {
md-fab-trigger {
.md-button {
&.md-fab {
opacity: 1;
@include transition(opacity .3s cubic-bezier(.55,0,.55,.2));
.md-fab-toolbar-background {
background-color: $primary-default !important;
}
}
}
}
}
md-fab-trigger {
.md-button {
&.md-fab {
line-height: 36px;
width: 36px;
height: 36px;
margin: 4px 0 0 4px;
opacity: 0.5;
@include transition(opacity .3s cubic-bezier(.55,0,.55,.2) .2s);
md-icon {
position: absolute;
top: 25%;
margin: 0;
line-height: 18px;
height: 18px;
width: 18px;
min-height: 18px;
min-width: 18px;
}
}
}
}
&.is-fullscreen {
&.md-is-open {
md-fab-trigger {
.md-button {
&.md-fab {
.md-fab-toolbar-background {
transition-delay: 0ms !important;
transition-duration: 0ms !important;
}
}
}
}
}
.md-fab-toolbar-wrapper {
height: 64px;
md-toolbar {
min-height: 64px;
height: 64px;
}
}
}
.md-fab-toolbar-wrapper {
height: 50px;
md-toolbar {
min-height: 50px;
height: 50px;
md-fab-actions {
font-size: 16px;
margin-top: 0px;
.close-action {
margin-right: -18px;
}
.md-fab-action-item {
width: 100%;
height: 46px;
.tb-dashboard-action-panels {
height: 46px;
flex-direction: row-reverse;
.tb-dashboard-action-panel {
height: 46px;
flex-direction: row-reverse;
div {
height: 46px;
}
md-select {
pointer-events: all;
}
tb-states-component {
pointer-events: all;
}
}
}
}
}
}
}
}
}

35
ui/src/app/dashboard/dashboard-toolbar.tpl.html

@ -0,0 +1,35 @@
<!--
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-fab-toolbar md-open="vm.toolbarOpened"
md-direction="left"
ng-class="{'is-fullscreen': vm.forceFullscreen, 'md-whiteframe-z1': vm.forceFullscreen}">
<md-fab-trigger class="align-with-text">
<md-button aria-label="menu" class="md-fab md-primary" ng-click="vm.onTriggerClick()">
<md-tooltip ng-show="!vm.toolbarOpened" md-direction="bottom">
{{ 'dashboard.open-toolbar' | translate }}
</md-tooltip>
<md-icon aria-label="dashboard-toolbar" class="material-icons">more_horiz</md-icon>
</md-button>
</md-fab-trigger>
<md-toolbar>
<md-fab-actions class="md-toolbar-tools">
<div ng-transclude></div>
</md-fab-actions>
</md-toolbar>
</md-fab-toolbar>

17
ui/src/app/dashboard/dashboard.controller.js

@ -63,7 +63,9 @@ export default function DashboardController(types, dashboardUtils, widgetService
} }
Object.defineProperty(vm, 'toolbarOpened', { Object.defineProperty(vm, 'toolbarOpened', {
get: function() { return !vm.widgetEditMode && ($scope.forceFullscreen || vm.isToolbarOpened || vm.isEdit || vm.showRightLayoutSwitch()); }, get: function() {
return !vm.widgetEditMode &&
(toolbarAlwaysOpen() || $scope.forceFullscreen || vm.isToolbarOpened || vm.isEdit || vm.showRightLayoutSwitch()); },
set: function() { } set: function() { }
}); });
@ -103,9 +105,11 @@ export default function DashboardController(types, dashboardUtils, widgetService
} }
vm.showCloseToolbar = function() { vm.showCloseToolbar = function() {
return !$scope.forceFullscreen && !vm.isEdit && !vm.showRightLayoutSwitch(); return !vm.toolbarAlwaysOpen() && !$scope.forceFullscreen && !vm.isEdit && !vm.showRightLayoutSwitch();
} }
vm.toolbarAlwaysOpen = toolbarAlwaysOpen;
vm.showRightLayoutSwitch = function() { vm.showRightLayoutSwitch = function() {
return vm.isMobile && vm.layouts.right.show; return vm.isMobile && vm.layouts.right.show;
} }
@ -738,6 +742,15 @@ export default function DashboardController(types, dashboardUtils, widgetService
return link; return link;
} }
function toolbarAlwaysOpen() {
if (vm.dashboard && vm.dashboard.configuration.settings &&
angular.isDefined(vm.dashboard.configuration.settings.toolbarAlwaysOpen)) {
return vm.dashboard.configuration.settings.toolbarAlwaysOpen;
} else {
return false;
}
}
function displayTitle() { function displayTitle() {
if (vm.dashboard && vm.dashboard.configuration.settings && if (vm.dashboard && vm.dashboard.configuration.settings &&
angular.isDefined(vm.dashboard.configuration.settings.showTitle)) { angular.isDefined(vm.dashboard.configuration.settings.showTitle)) {

80
ui/src/app/dashboard/dashboard.scss

@ -68,87 +68,23 @@ section.tb-dashboard-toolbar {
pointer-events: none; pointer-events: none;
&.tb-dashboard-toolbar-opened { &.tb-dashboard-toolbar-opened {
right: 0px; right: 0px;
@include transition(right .3s cubic-bezier(.55,0,.55,.2)); // @include transition(right .3s cubic-bezier(.55,0,.55,.2));
} }
&.tb-dashboard-toolbar-closed { &.tb-dashboard-toolbar-closed {
right: 18px; right: 18px;
@include transition(right .3s cubic-bezier(.55,0,.55,.2) .2s); @include transition(right .3s cubic-bezier(.55,0,.55,.2) .2s);
} }
md-fab-toolbar {
&.md-is-open {
md-fab-trigger {
.md-button {
&.md-fab {
opacity: 1;
@include transition(opacity .3s cubic-bezier(.55,0,.55,.2));
}
}
}
}
md-fab-trigger {
.md-button {
&.md-fab {
line-height: 36px;
width: 36px;
height: 36px;
margin: 4px 0 0 4px;
opacity: 0.5;
@include transition(opacity .3s cubic-bezier(.55,0,.55,.2) .2s);
md-icon {
position: absolute;
top: 25%;
margin: 0;
line-height: 18px;
height: 18px;
width: 18px;
min-height: 18px;
min-width: 18px;
}
}
}
}
.md-fab-toolbar-wrapper {
height: 50px;
md-toolbar {
min-height: 46px;
height: 46px;
md-fab-actions {
font-size: 16px;
margin-top: 0px;
.close-action {
margin-right: -18px;
}
.md-fab-action-item {
width: 100%;
height: 46px;
.tb-dashboard-action-panels {
height: 46px;
flex-direction: row-reverse;
.tb-dashboard-action-panel {
height: 46px;
flex-direction: row-reverse;
div {
height: 46px;
}
md-select {
pointer-events: all;
}
tb-states-component {
pointer-events: all;
}
}
}
}
}
}
}
}
} }
.tb-dashboard-container { .tb-dashboard-container {
&.tb-dashboard-toolbar-opened { &.tb-dashboard-toolbar-opened {
margin-top: 50px; &.is-fullscreen {
@include transition(margin-top .3s cubic-bezier(.55,0,.55,.2)); margin-top: 64px;
}
&:not(.is-fullscreen) {
margin-top: 50px;
@include transition(margin-top .3s cubic-bezier(.55,0,.55,.2));
}
} }
&.tb-dashboard-toolbar-closed { &.tb-dashboard-toolbar-closed {
margin-top: 0px; margin-top: 0px;

190
ui/src/app/dashboard/dashboard.tpl.html

@ -19,110 +19,98 @@
hide-expand-button="vm.widgetEditMode || vm.iframeMode || forceFullscreen" expand-tooltip-direction="bottom"> hide-expand-button="vm.widgetEditMode || vm.iframeMode || forceFullscreen" expand-tooltip-direction="bottom">
<section class="tb-dashboard-toolbar" ng-show="vm.showDashboardToolbar()" <section class="tb-dashboard-toolbar" ng-show="vm.showDashboardToolbar()"
ng-class="{ 'tb-dashboard-toolbar-opened': vm.toolbarOpened, 'tb-dashboard-toolbar-closed': !vm.toolbarOpened }"> ng-class="{ 'tb-dashboard-toolbar-opened': vm.toolbarOpened, 'tb-dashboard-toolbar-closed': !vm.toolbarOpened }">
<md-fab-toolbar ng-show="!vm.widgetEditMode" md-open="vm.toolbarOpened" <tb-dashboard-toolbar ng-show="!vm.widgetEditMode" force-fullscreen="forceFullscreen"
md-direction="left"> toolbar-opened="vm.toolbarOpened" on-trigger-click="vm.openToolbar()">
<md-fab-trigger class="align-with-text"> <div class="tb-dashboard-action-panels" flex layout="row" layout-align="start center">
<md-button aria-label="menu" class="md-fab md-primary" ng-click="vm.openToolbar()"> <div class="tb-dashboard-action-panel" flex="50" layout="row" layout-align="start center">
<md-tooltip ng-show="!vm.toolbarOpened" md-direction="bottom"> <md-button ng-show="vm.showCloseToolbar()" aria-label="close-toolbar" class="md-icon-button close-action" ng-click="vm.closeToolbar()">
{{ 'dashboard.open-toolbar' | translate }} <md-tooltip md-direction="bottom">
</md-tooltip> {{ 'dashboard.close-toolbar' | translate }}
<md-icon aria-label="dashboard-toolbar" class="material-icons">more_horiz</md-icon> </md-tooltip>
</md-button> <md-icon aria-label="close-toolbar" class="material-icons">arrow_forward</md-icon>
</md-fab-trigger> </md-button>
<md-toolbar> <md-button ng-show="vm.showRightLayoutSwitch()" aria-label="switch-layouts" class="md-icon-button" ng-click="vm.toggleLayouts()">
<md-fab-actions class="md-toolbar-tools"> <ng-md-icon icon="{{vm.isRightLayoutOpened ? 'arrow_back' : 'menu'}}" options='{"easing": "circ-in-out", "duration": 375, "rotation": "none"}'></ng-md-icon>
<div class="tb-dashboard-action-panels" flex layout="row" layout-align="start center"> <md-tooltip md-direction="bottom">
<div class="tb-dashboard-action-panel" flex="50" layout="row" layout-align="start center"> {{ (vm.isRightLayoutOpened ? 'dashboard.hide-details' : 'dashboard.show-details') | translate }}
<md-button ng-show="vm.showCloseToolbar()" aria-label="close-toolbar" class="md-icon-button close-action" ng-click="vm.closeToolbar()"> </md-tooltip>
<md-tooltip md-direction="bottom"> </md-button>
{{ 'dashboard.close-toolbar' | translate }} <md-button id="dashboard-expand-button"
</md-tooltip> aria-label="{{ 'fullscreen.fullscreen' | translate }}"
<md-icon aria-label="close-toolbar" class="material-icons">arrow_forward</md-icon> class="md-icon-button">
</md-button> </md-button>
<md-button ng-show="vm.showRightLayoutSwitch()" aria-label="switch-layouts" class="md-icon-button" ng-click="vm.toggleLayouts()"> <tb-user-menu ng-if="!vm.isPublicUser() && forceFullscreen" display-user-info="true">
<ng-md-icon icon="{{vm.isRightLayoutOpened ? 'arrow_back' : 'menu'}}" options='{"easing": "circ-in-out", "duration": 375, "rotation": "none"}'></ng-md-icon> </tb-user-menu>
<md-tooltip md-direction="bottom"> <md-button ng-show="vm.isEdit || vm.displayExport()"
{{ (vm.isRightLayoutOpened ? 'dashboard.hide-details' : 'dashboard.show-details') | translate }} aria-label="{{ 'action.export' | translate }}" class="md-icon-button"
</md-tooltip> ng-click="vm.exportDashboard($event)">
</md-button> <md-tooltip md-direction="bottom">
<md-button id="dashboard-expand-button" {{ 'dashboard.export' | translate }}
aria-label="{{ 'fullscreen.fullscreen' | translate }}" </md-tooltip>
class="md-icon-button"> <md-icon aria-label="{{ 'action.export' | translate }}" class="material-icons">file_download</md-icon>
</md-button> </md-button>
<tb-user-menu ng-if="!vm.isPublicUser() && forceFullscreen" display-user-info="true"> <tb-timewindow ng-show="vm.isEdit || vm.displayDashboardTimewindow()"
</tb-user-menu> is-toolbar
<md-button ng-show="vm.isEdit || vm.displayExport()" direction="left"
aria-label="{{ 'action.export' | translate }}" class="md-icon-button" tooltip-direction="bottom" aggregation
ng-click="vm.exportDashboard($event)"> ng-model="vm.dashboardCtx.dashboardTimewindow">
<md-tooltip md-direction="bottom"> </tb-timewindow>
{{ 'dashboard.export' | translate }} <tb-aliases-entity-select ng-show="!vm.isEdit && vm.displayEntitiesSelect()"
</md-tooltip> tooltip-direction="bottom"
<md-icon aria-label="{{ 'action.export' | translate }}" class="material-icons">file_download</md-icon> ng-model="vm.dashboardCtx.aliasesInfo.entityAliases"
</md-button> entity-aliases-info="vm.dashboardCtx.aliasesInfo.entityAliasesInfo">
<tb-timewindow ng-show="vm.isEdit || vm.displayDashboardTimewindow()" </tb-aliases-entity-select>
is-toolbar <md-button ng-show="vm.isEdit" aria-label="{{ 'entity.aliases' | translate }}" class="md-icon-button"
direction="left" ng-click="vm.openEntityAliases($event)">
tooltip-direction="bottom" aggregation <md-tooltip md-direction="bottom">
ng-model="vm.dashboardCtx.dashboardTimewindow"> {{ 'entity.aliases' | translate }}
</tb-timewindow> </md-tooltip>
<tb-aliases-entity-select ng-show="!vm.isEdit && vm.displayEntitiesSelect()" <md-icon aria-label="{{ 'entity.aliases' | translate }}" class="material-icons">devices_other</md-icon>
tooltip-direction="bottom" </md-button>
ng-model="vm.dashboardCtx.aliasesInfo.entityAliases" <md-button ng-show="vm.isEdit" aria-label="{{ 'dashboard.settings' | translate }}" class="md-icon-button"
entity-aliases-info="vm.dashboardCtx.aliasesInfo.entityAliasesInfo"> ng-click="vm.openDashboardSettings($event)">
</tb-aliases-entity-select> <md-tooltip md-direction="bottom">
<md-button ng-show="vm.isEdit" aria-label="{{ 'entity.aliases' | translate }}" class="md-icon-button" {{ 'dashboard.settings' | translate }}
ng-click="vm.openEntityAliases($event)"> </md-tooltip>
<md-tooltip md-direction="bottom"> <md-icon aria-label="{{ 'dashboard.settings' | translate }}" class="material-icons">settings</md-icon>
{{ 'entity.aliases' | translate }} </md-button>
</md-tooltip> <tb-dashboard-select ng-show="!vm.isEdit && !vm.widgetEditMode && vm.displayDashboardsSelect()"
<md-icon aria-label="{{ 'entity.aliases' | translate }}" class="material-icons">devices_other</md-icon> ng-model="vm.currentDashboardId"
</md-button> dashboards-scope="{{vm.currentDashboardScope}}"
<md-button ng-show="vm.isEdit" aria-label="{{ 'dashboard.settings' | translate }}" class="md-icon-button" customer-id="vm.currentCustomerId">
ng-click="vm.openDashboardSettings($event)"> </tb-dashboard-select>
<md-tooltip md-direction="bottom"> </div>
{{ 'dashboard.settings' | translate }} <div class="tb-dashboard-action-panel" flex="50" layout="row" layout-align="end center">
</md-tooltip> <div layout="row" layout-align="start center" ng-show="vm.isEdit">
<md-icon aria-label="{{ 'dashboard.settings' | translate }}" class="material-icons">settings</md-icon> <md-button aria-label="{{ 'dashboard.manage-states' | translate }}" class="md-icon-button"
</md-button> ng-click="vm.manageDashboardStates($event)">
<tb-dashboard-select ng-show="!vm.isEdit && !vm.widgetEditMode && vm.displayDashboardsSelect()" <md-tooltip md-direction="bottom">
ng-model="vm.currentDashboardId" {{ 'dashboard.manage-states' | translate }}
dashboards-scope="{{vm.currentDashboardScope}}" </md-tooltip>
customer-id="vm.currentCustomerId"> <md-icon aria-label="{{ 'dashboard.manage-states' | translate }}" class="material-icons">layers</md-icon>
</tb-dashboard-select> </md-button>
</div> <md-button aria-label="{{ 'layout.manage' | translate }}" class="md-icon-button"
<div class="tb-dashboard-action-panel" flex="50" layout="row" layout-align="end center"> ng-click="vm.manageDashboardLayouts($event)">
<div layout="row" layout-align="start center" ng-show="vm.isEdit"> <md-tooltip md-direction="bottom">
<md-button aria-label="{{ 'dashboard.manage-states' | translate }}" class="md-icon-button" {{ 'layout.manage' | translate }}
ng-click="vm.manageDashboardStates($event)"> </md-tooltip>
<md-tooltip md-direction="bottom"> <md-icon aria-label="{{ 'layout.manage' | translate }}" class="material-icons">view_compact</md-icon>
{{ 'dashboard.manage-states' | translate }} </md-button>
</md-tooltip>
<md-icon aria-label="{{ 'dashboard.manage-states' | translate }}" class="material-icons">layers</md-icon>
</md-button>
<md-button aria-label="{{ 'layout.manage' | translate }}" class="md-icon-button"
ng-click="vm.manageDashboardLayouts($event)">
<md-tooltip md-direction="bottom">
{{ 'layout.manage' | translate }}
</md-tooltip>
<md-icon aria-label="{{ 'layout.manage' | translate }}" class="material-icons">view_compact</md-icon>
</md-button>
</div>
<div layout="row" layout-align="start center">
<tb-states-component ng-if="vm.isEdit" states-controller-id="'default'"
dashboard-ctrl="vm" states="vm.dashboardConfiguration.states">
</tb-states-component>
<tb-states-component ng-if="!vm.isEdit" states-controller-id="vm.dashboardConfiguration.settings.stateControllerId"
dashboard-ctrl="vm" states="vm.dashboardConfiguration.states">
</tb-states-component>
</div>
</div>
</div> </div>
</md-fab-actions> <div layout="row" layout-align="start center">
</md-toolbar> <tb-states-component ng-if="vm.isEdit" states-controller-id="'default'"
</md-fab-toolbar> dashboard-ctrl="vm" states="vm.dashboardConfiguration.states">
</tb-states-component>
<tb-states-component ng-if="!vm.isEdit" states-controller-id="vm.dashboardConfiguration.settings.stateControllerId"
dashboard-ctrl="vm" states="vm.dashboardConfiguration.states">
</tb-states-component>
</div>
</div>
</div>
</tb-dashboard-toolbar>
</section> </section>
<section class="tb-dashboard-container tb-absolute-fill" <section class="tb-dashboard-container tb-absolute-fill"
ng-class="{ 'tb-dashboard-toolbar-opened': vm.toolbarOpened, 'tb-dashboard-toolbar-closed': !vm.toolbarOpened }"> ng-class="{ 'is-fullscreen': forceFullscreen, 'tb-dashboard-toolbar-opened': vm.toolbarOpened, 'tb-dashboard-toolbar-closed': !vm.toolbarOpened }">
<section ng-show="!loading && vm.dashboardConfigurationError()" layout-align="center center" <section ng-show="!loading && vm.dashboardConfigurationError()" layout-align="center center"
ng-style="{'color': vm.dashboard.configuration.settings.titleColor}" ng-style="{'color': vm.dashboard.configuration.settings.titleColor}"
ng-class="{'tb-padded' : !vm.widgetEditMode}" ng-class="{'tb-padded' : !vm.widgetEditMode}"

2
ui/src/app/dashboard/index.js

@ -45,6 +45,7 @@ import AddDashboardsToCustomerController from './add-dashboards-to-customer.cont
import AddWidgetController from './add-widget.controller'; import AddWidgetController from './add-widget.controller';
import DashboardDirective from './dashboard.directive'; import DashboardDirective from './dashboard.directive';
import EditWidgetDirective from './edit-widget.directive'; import EditWidgetDirective from './edit-widget.directive';
import DashboardToolbar from './dashboard-toolbar.directive';
export default angular.module('thingsboard.dashboard', [ export default angular.module('thingsboard.dashboard', [
uiRouter, uiRouter,
@ -78,4 +79,5 @@ export default angular.module('thingsboard.dashboard', [
.controller('AddWidgetController', AddWidgetController) .controller('AddWidgetController', AddWidgetController)
.directive('tbDashboardDetails', DashboardDirective) .directive('tbDashboardDetails', DashboardDirective)
.directive('tbEditWidget', EditWidgetDirective) .directive('tbEditWidget', EditWidgetDirective)
.directive('tbDashboardToolbar', DashboardToolbar)
.name; .name;

1
ui/src/app/locale/locale.constant.js

@ -328,6 +328,7 @@ export default angular.module('thingsboard.locale', [])
"min-vertical-margin-message": "Only 0 is allowed as minimum vertical margin value.", "min-vertical-margin-message": "Only 0 is allowed as minimum vertical margin value.",
"max-vertical-margin-message": "Only 50 is allowed as maximum vertical margin value.", "max-vertical-margin-message": "Only 50 is allowed as maximum vertical margin value.",
"display-title": "Display dashboard title", "display-title": "Display dashboard title",
"toolbar-always-open": "Keep toolbar opened",
"title-color": "Title color", "title-color": "Title color",
"display-dashboards-selection": "Display dashboards selection", "display-dashboards-selection": "Display dashboards selection",
"display-entities-selection": "Display entities selection", "display-entities-selection": "Display entities selection",

2
ui/src/scss/constants.scss

@ -20,10 +20,12 @@
$gray: #eee; $gray: #eee;
$primary-palette-color: 'indigo'; $primary-palette-color: 'indigo';
$default: '500';
$hue-1: '300'; $hue-1: '300';
$hue-2: '800'; $hue-2: '800';
$hue-3: 'a100'; $hue-3: 'a100';
$primary-default: #305680; //material-color($primary-palette-color, $default);
$primary-hue-1: material-color($primary-palette-color, $hue-1); $primary-hue-1: material-color($primary-palette-color, $hue-1);
$primary-hue-2: material-color($primary-palette-color, $hue-2); $primary-hue-2: material-color($primary-palette-color, $hue-2);
$primary-hue-3: rgb(207, 216, 220); $primary-hue-3: rgb(207, 216, 220);

Loading…
Cancel
Save