dashboard.tpl.html 21.8 KB
<!--

    Copyright © 2016-2020 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-content style="padding-top: 150px;" flex tb-expand-fullscreen="vm.widgetEditMode || vm.iframeMode || forceFullscreen" expand-button-id="dashboard-expand-button"
            hide-expand-button="vm.hideFullscreenButton()" expand-tooltip-direction="bottom" ng-if="vm.dashboard">
    <section class="tb-dashboard-toolbar" ng-show="vm.showDashboardToolbar()"
             ng-class="{ 'tb-dashboard-toolbar-opened': vm.toolbarOpened, 'tb-dashboard-toolbar-closed': !vm.toolbarOpened }">
        <tb-dashboard-toolbar ng-show="!vm.widgetEditMode" force-fullscreen="forceFullscreen"
                              toolbar-opened="vm.toolbarOpened" on-trigger-click="vm.openToolbar()">
            <div class="tb-dashboard-action-panels" layout-sm="column" layout-xs="column" layout-align-gt-sm="space-between center" layout="row" layout-align="center stretch">
                <div class="tb-dashboard-action-panel" flex-md="30" layout="row" layout-align-gt-sm="start center" layout-align="space-between center">
                    <md-button ng-show="vm.showCloseToolbar()" aria-label="close-toolbar" class="md-icon-button close-action" ng-click="vm.closeToolbar()">
                        <md-tooltip md-direction="bottom">
                            {{ 'dashboard.close-toolbar' | translate }}
                        </md-tooltip>
                        <md-icon aria-label="close-toolbar" class="material-icons">arrow_forward</md-icon>
                    </md-button>
                    <tb-user-menu ng-if="!vm.isPublicUser() && forceFullscreen" hide-xs hide-sm display-user-info="true">
                    </tb-user-menu>
                    <md-button ng-show="vm.showRightLayoutSwitch()" aria-label="switch-layouts" class="md-icon-button" ng-click="vm.toggleLayouts()">
                        <ng-md-icon icon="{{vm.isRightLayoutOpened ? 'arrow_back' : 'menu'}}" options='{"easing": "circ-in-out", "duration": 375, "rotation": "none"}'></ng-md-icon>
                        <md-tooltip md-direction="bottom">
                            {{ (vm.isRightLayoutOpened ? 'dashboard.hide-details' : 'dashboard.show-details') | translate }}
                        </md-tooltip>
                    </md-button>
                    <md-button id="dashboard-expand-button"
                               aria-label="{{ 'fullscreen.fullscreen' | translate }}"
                               class="md-icon-button">
                    </md-button>
                    <md-button ng-show="vm.isEdit || vm.displayExport()"
                               aria-label="{{ 'action.export' | translate }}" class="md-icon-button"
                               ng-click="vm.exportDashboard($event)">
                        <md-tooltip md-direction="bottom">
                            {{ 'dashboard.export' | translate }}
                        </md-tooltip>
                        <md-icon aria-label="{{ 'action.export' | translate }}" class="material-icons">file_download</md-icon>
                    </md-button>
                    <tb-timewindow ng-show="vm.isEdit || vm.displayDashboardTimewindow()"
                                   is-toolbar is-edit="vm.isEdit"
                                   direction="left"
                                   tooltip-direction="bottom" aggregation="true"
                                   ng-model="vm.dashboardCtx.dashboardTimewindow">
                    </tb-timewindow>
                    <tb-aliases-entity-select ng-show="!vm.isEdit && vm.displayEntitiesSelect()"
                                              tooltip-direction="bottom"
                                              alias-controller="vm.dashboardCtx.aliasController">
                    </tb-aliases-entity-select>
                    <md-button ng-show="vm.isEdit" aria-label="{{ 'entity.aliases' | translate }}" class="md-icon-button"
                               ng-click="vm.openEntityAliases($event)">
                        <md-tooltip md-direction="bottom">
                            {{ 'entity.aliases' | translate }}
                        </md-tooltip>
                        <md-icon aria-label="{{ 'entity.aliases' | translate }}" class="material-icons">devices_other</md-icon>
                    </md-button>
                    <md-button ng-show="vm.isEdit" aria-label="{{ 'dashboard.settings' | translate }}" class="md-icon-button"
                               ng-click="vm.openDashboardSettings($event)">
                        <md-tooltip md-direction="bottom">
                            {{ 'dashboard.settings' | translate }}
                        </md-tooltip>
                        <md-icon aria-label="{{ 'dashboard.settings' | translate }}" class="material-icons">settings</md-icon>
                    </md-button>
                    <tb-dashboard-select   ng-show="!vm.isEdit && !vm.widgetEditMode && vm.displayDashboardsSelect()"
                                           ng-model="vm.currentDashboardId"
                                           dashboards-scope="{{vm.currentDashboardScope}}"
                                           customer-id="vm.currentCustomerId">
                    </tb-dashboard-select>
                </div>
                <div class="tb-dashboard-action-panel" flex-md="70" layout="row" layout-align-gt-sm="end center" layout-align="space-between center">
                    <tb-user-menu ng-if="!vm.isPublicUser() && forceFullscreen" hide-gt-sm display-user-info="true">
                    </tb-user-menu>
                    <div flex-xs flex-sm layout="row" layout-align-gt-sm="start center" layout-align="space-between center" ng-show="vm.isEdit">
                        <md-button aria-label="{{ 'dashboard.manage-states' | translate }}" class="md-icon-button"
                                   ng-click="vm.manageDashboardStates($event)">
                            <md-tooltip md-direction="bottom">
                                {{ 'dashboard.manage-states' | translate }}
                            </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>
                    <tb-states-component flex-xs flex-sm ng-if="vm.isEdit" states-controller-id="'default'"
                                         dashboard-ctrl="vm" states="vm.dashboardConfiguration.states">
                    </tb-states-component>
                    <tb-states-component flex-xs flex-sm ng-if="!vm.isEdit" states-controller-id="vm.dashboardConfiguration.settings.stateControllerId"
                                         dashboard-ctrl="vm" states="vm.dashboardConfiguration.states">
                    </tb-states-component>
                 </div>
            </div>
        </tb-dashboard-toolbar>
    </section>
    <section class="tb-dashboard-container tb-absolute-fill"
             ng-class="{ 'is-fullscreen': forceFullscreen, 'tb-dashboard-toolbar-opened': vm.toolbarOpened, 'tb-dashboard-toolbar-closed': !vm.toolbarOpened }">
        <section ng-show="!$root.loading && vm.dashboardConfigurationError()" layout-align="center center"
                 ng-style="{'color': vm.dashboard.configuration.settings.titleColor}"
                 ng-class="{'tb-padded' : !vm.widgetEditMode}"
                 style="text-transform: uppercase; display: flex; z-index: 1;"
                 class="md-headline tb-absolute-fill">
            <span translate>
                dashboard.configuration-error
            </span>
        </section>
        <section ng-if="!vm.widgetEditMode" class="tb-dashboard-title" layout="row" layout-align="center center"
                 ng-style="{'color': vm.dashboard.configuration.settings.titleColor}">
            <h3 ng-show="!vm.isEdit && vm.displayTitle()">{{ vm.dashboard.title }}</h3>
            <md-input-container ng-show="vm.isEdit" class="md-block" style="height: 30px;">
                <label translate ng-style="{'color': vm.dashboard.configuration.settings.titleColor}">dashboard.title</label>
                <input class="tb-dashboard-title" ng-style="{'color': vm.dashboard.configuration.settings.titleColor}" required name="title" ng-model="vm.dashboard.title">
            </md-input-container>
        </section>
        <div class="tb-absolute-fill tb-dashboard-layouts" layout="{{vm.forceDashboardMobileMode ? 'column' : 'row'}}"
             ng-class="{ 'tb-padded' : !vm.widgetEditMode && (vm.isEdit || vm.displayTitle()), 'tb-shrinked' : vm.isEditingWidget }">
            <div ng-show="vm.layouts.main.show"
                 id="tb-main-layout"
                 ng-style="{width: vm.mainLayoutWidth(),
                            height: vm.mainLayoutHeight()}">
                <tb-dashboard-layout layout-ctx="vm.layouts.main.layoutCtx"
                                     dashboard-ctx="vm.dashboardCtx"
                                     is-edit="vm.isEdit"
                                     is-mobile="vm.forceDashboardMobileMode"
                                     widget-edit-mode="vm.widgetEditMode">
                </tb-dashboard-layout>
            </div>
            <md-sidenav ng-if="vm.layouts.right.show"
                        id="tb-right-layout"
                        class="md-sidenav-right"
                        ng-style="{minWidth: vm.rightLayoutWidth(),
                                   maxWidth: vm.rightLayoutWidth(),
                                   height: vm.rightLayoutHeight(),
                                   zIndex: 25}"
                        md-component-id="right-dashboard-layout"
                        aria-label="Right dashboard layout"
                        md-is-open="vm.rightLayoutOpened"
                        md-is-locked-open="!vm.isMobile">
                <tb-dashboard-layout style="height: 100%;"
                                     layout-ctx="vm.layouts.right.layoutCtx"
                                     dashboard-ctx="vm.dashboardCtx"
                                     is-edit="vm.isEdit"
                                     is-mobile="vm.forceDashboardMobileMode"
                                     widget-edit-mode="vm.widgetEditMode">
                </tb-dashboard-layout>
            </md-sidenav>
        </div>
        <tb-details-sidenav class="tb-widget-details-sidenav"
                            header-title="{{vm.editingWidget.config.title}}"
                            header-subtitle="{{vm.editingWidgetSubtitle}}"
                            is-read-only="false"
                            is-open="vm.isEditingWidget"
                            is-always-edit="true"
                            on-close-details="vm.onEditWidgetClosed()"
                            on-toggle-details-edit-mode="vm.onRevertWidgetEdit(vm.widgetForm)"
                            on-apply-details="vm.saveWidget(vm.widgetForm)"
                            the-form="vm.widgetForm">
            <details-buttons tb-help="vm.helpLinkIdForWidgetType()" help-container-id="help-container">
                <div id="help-container"></div>
            </details-buttons>
            <form name="vm.widgetForm" ng-if="vm.isEditingWidget">
                <tb-edit-widget
                        dashboard="vm.dashboard"
                        alias-controller="vm.dashboardCtx.aliasController"
                        widget-edit-mode="vm.widgetEditMode"
                        widget="vm.editingWidget"
                        widget-layout="vm.editingWidgetLayout"
                        the-form="vm.widgetForm">
                </tb-edit-widget>
            </form>
        </tb-details-sidenav>
        <tb-details-sidenav ng-if="!vm.widgetEditMode" class="tb-select-widget-sidenav"
                            header-title="{{'dashboard.select-widget-title' | translate}}"
                            header-height-px="120"
                            is-read-only="true"
                            is-open="vm.isAddingWidget"
                            is-edit="false"
                            on-close-details="vm.onAddWidgetClosed()">
            <header-pane ng-if="vm.isAddingWidget">
                <div layout="row">
                    <span class="tb-details-subtitle">{{ 'widgets-bundle.current' | translate }}</span>
                    <tb-widgets-bundle-select flex-offset="5"
                                              flex
                            ng-model="vm.widgetsBundle"
                            tb-required="true"
                            select-first-bundle="false">
                    </tb-widgets-bundle-select>
                </div>
            </header-pane>
            <div ng-if="vm.isAddingWidget">
                <md-tabs ng-if="vm.timeseriesWidgetTypes.length > 0 || vm.latestWidgetTypes.length > 0 ||
                                vm.rpcWidgetTypes.length > 0 || vm.alarmWidgetTypes.length > 0 ||
                                vm.staticWidgetTypes.length > 0"
                         flex
                         class="tb-absolute-fill" md-border-bottom>
                    <md-tab ng-if="vm.timeseriesWidgetTypes.length > 0" style="height: 100%;" label="{{ 'widget.timeseries' | translate }}">
                        <tb-dashboard
                                alias-controller="vm.dashboardCtx.aliasController"
                                widgets="vm.timeseriesWidgetTypes"
                                is-edit="false"
                                is-mobile="true"
                                is-edit-action-enabled="false"
                                is-remove-action-enabled="false"
                                on-widget-clicked="vm.addWidgetFromType(event, widget)">
                        </tb-dashboard>
                    </md-tab>
                    <md-tab ng-if="vm.latestWidgetTypes.length > 0" style="height: 100%;" label="{{ 'widget.latest-values' | translate }}">
                        <tb-dashboard
                                alias-controller="vm.dashboardCtx.aliasController"
                                widgets="vm.latestWidgetTypes"
                                is-edit="false"
                                is-mobile="true"
                                is-edit-action-enabled="false"
                                is-remove-action-enabled="false"
                                on-widget-clicked="vm.addWidgetFromType(event, widget)">
                        </tb-dashboard>
                    </md-tab>
                    <md-tab ng-if="vm.rpcWidgetTypes.length > 0" style="height: 100%;" label="{{ 'widget.rpc' | translate }}">
                        <tb-dashboard
                                alias-controller="vm.dashboardCtx.aliasController"
                                widgets="vm.rpcWidgetTypes"
                                is-edit="false"
                                is-mobile="true"
                                is-edit-action-enabled="false"
                                is-remove-action-enabled="false"
                                on-widget-clicked="vm.addWidgetFromType(event, widget)">
                        </tb-dashboard>
                    </md-tab>
                    <md-tab ng-if="vm.alarmWidgetTypes.length > 0" style="height: 100%;" label="{{ 'widget.alarm' | translate }}">
                        <tb-dashboard
                                alias-controller="vm.dashboardCtx.aliasController"
                                widgets="vm.alarmWidgetTypes"
                                is-edit="false"
                                is-mobile="true"
                                is-edit-action-enabled="false"
                                is-remove-action-enabled="false"
                                on-widget-clicked="vm.addWidgetFromType(event, widget)">
                        </tb-dashboard>
                    </md-tab>
                    <md-tab ng-if="vm.staticWidgetTypes.length > 0" style="height: 100%;" label="{{ 'widget.static' | translate }}">
                        <tb-dashboard
                                alias-controller="vm.dashboardCtx.aliasController"
                                widgets="vm.staticWidgetTypes"
                                is-edit="false"
                                is-mobile="true"
                                is-edit-action-enabled="false"
                                is-remove-action-enabled="false"
                                on-widget-clicked="vm.addWidgetFromType(event, widget)">
                        </tb-dashboard>
                    </md-tab>
                </md-tabs>
                <span translate ng-if="vm.timeseriesWidgetTypes.length === 0 && vm.latestWidgetTypes.length === 0 &&
                                       vm.rpcWidgetTypes.length === 0 && vm.alarmWidgetTypes.length === 0 &&
                                       vm.staticWidgetTypes.length === 0 && vm.widgetsBundle"
                      layout-align="center center"
                      style="text-transform: uppercase; display: flex;"
                      class="md-headline tb-absolute-fill">widgets-bundle.empty</span>
                <span translate ng-if="!vm.widgetsBundle"
                      layout-align="center center"
                      style="text-transform: uppercase; display: flex;"
                      class="md-headline tb-absolute-fill">widget.select-widgets-bundle</span>
            </div>
        </tb-details-sidenav>
        <section layout="row" layout-wrap class="tb-footer-buttons md-fab" layout-align="start end">
            <md-fab-speed-dial ng-disabled="$root.loading" ng-show="!vm.isAddingWidget && vm.isEdit && !vm.widgetEditMode"
                               md-open="vm.addItemActionsOpen" class="md-scale" md-direction="up">
                <md-fab-trigger>
                    <md-button ng-disabled="$root.loading"
                               class="tb-btn-footer md-accent md-hue-2 md-fab"
                               aria-label="{{ 'dashboard.add-widget' | translate }}">
                        <md-tooltip md-direction="top">
                            {{ 'dashboard.add-widget' | translate }}
                        </md-tooltip>
                        <ng-md-icon icon="add"></ng-md-icon>
                    </md-button>
                </md-fab-trigger>
                <md-fab-actions>
                    <md-button ng-disabled="$root.loading"
                               class="tmd-accent md-hue-2 md-fab" ng-click="vm.addWidget($event)"
                               aria-label="{{ 'action.create' | translate }}">
                        <md-tooltip md-direction="top">
                            {{ 'dashboard.create-new-widget' | translate }}
                        </md-tooltip>
                        <ng-md-icon icon="insert_drive_file"></ng-md-icon>
                    </md-button>
                    <md-button ng-disabled="$root.loading"
                               class="tmd-accent md-hue-2 md-fab" ng-click="vm.importWidget($event)"
                               aria-label="{{ 'action.import' | translate }}">
                        <md-tooltip md-direction="top">
                            {{ 'dashboard.import-widget' | translate }}
                        </md-tooltip>
                        <ng-md-icon icon="file_upload"></ng-md-icon>
                    </md-button>
                </md-fab-actions>
            </md-fab-speed-dial>
            <md-button ng-if="(vm.isTenantAdmin() || vm.isSystemAdmin()) && !forceFullscreen" ng-show="vm.isEdit && !vm.isAddingWidget && !$root.loading" ng-disabled="$root.loading"
                       class="tb-btn-footer md-accent md-hue-2 md-fab"
                       aria-label="{{ 'action.apply' | translate }}"
                       ng-click="vm.saveDashboard()">
                <md-tooltip md-direction="top">
                    {{ 'action.apply-changes' | translate }}
                </md-tooltip>
                <ng-md-icon icon="done"></ng-md-icon>
            </md-button>
            <md-button ng-show="!vm.isAddingWidget && !$root.loading"
                       ng-if="(vm.isTenantAdmin() || vm.isSystemAdmin()) && !forceFullscreen" ng-disabled="$root.loading"
                       class="tb-btn-footer md-accent md-hue-2 md-fab"
                       aria-label="{{ 'action.edit-mode' | translate }}"
                       ng-click="vm.toggleDashboardEditMode()">
                <md-tooltip md-direction="top">
                    {{ (vm.isEdit ? 'action.decline-changes' : 'action.enter-edit-mode') | translate }}
                </md-tooltip>
                <ng-md-icon icon="{{vm.isEdit ? 'close' : 'edit'}}"
                            options='{"easing": "circ-in-out", "duration": 375, "rotation": "none"}'></ng-md-icon>
            </md-button>
        </section>
    </section>
    <section class="tb-powered-by-footer" ng-style="{'color': vm.dashboard.configuration.settings.titleColor}">
        <span>Powered by <a href="https://thingsboard.io" target="_blank">Thingsboard v.{{ vm.thingsboardVersion }}</a></span>
    </section>
</md-content>