/* * 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 './grid.scss'; import thingsboardScopeElement from './scope-element.directive'; import thingsboardDetailsSidenav from './details-sidenav.directive'; /* eslint-disable import/no-unresolved, import/default */ import gridTemplate from './grid.tpl.html'; /* eslint-enable import/no-unresolved, import/default */ export default angular.module('thingsboard.directives.grid', [thingsboardScopeElement, thingsboardDetailsSidenav]) .directive('tbGrid', Grid) .directive('tbGridCardContent', GridCardContent) .filter('range', RangeFilter) .name; /*@ngInject*/ function RangeFilter() { return function(input, total) { total = parseInt(total); for (var i=0; i= vm.items.rowData.length) { vm.itemRows.fetchMoreItems_(index); return null; } return vm.items.rowData[index]; }, getLength: function () { if (vm.items.hasNext) { return vm.items.rowData.length + pageSize; } else { return vm.items.rowData.length; } }, fetchMoreItems_: function () { if (vm.items.hasNext && !vm.items.pending) { var promise = vm.fetchItemsFunc(vm.items.nextPageLink); if (promise) { vm.items.pending = true; promise.then( function success(items) { vm.items.data = vm.items.data.concat(items.data); var startIndex = vm.items.data.length - items.data.length; var endIndex = vm.items.data.length; for (var i = startIndex; i < endIndex; i++) { var item = vm.items.data[i]; item.index = i; var row = Math.floor(i / vm.columns); var itemRow = vm.items.rowData[row]; if (!itemRow) { itemRow = []; vm.items.rowData.push(itemRow); } itemRow.push(item); } vm.items.nextPageLink = items.nextPageLink; vm.items.hasNext = items.hasNext; if (vm.items.hasNext) { vm.items.nextPageLink.limit = pageSize; } vm.items.pending = false; }, function fail() { vm.items.hasNext = false; vm.items.pending = false; }); } else { vm.items.hasNext = false; } } } }; function columnsUpdated(newColumns) { if (vm.columns !== newColumns) { var newTopIndex = Math.ceil(vm.columns * vm.topIndex / newColumns); pageSize = 10 * newColumns; vm.items.rowData = []; if (vm.items.nextPageLink) { vm.items.nextPageLink.limit = pageSize; } for (var i = 0; i < vm.items.data.length; i++) { var item = vm.items.data[i]; var row = Math.floor(i / newColumns); var itemRow = vm.items.rowData[row]; if (!itemRow) { itemRow = []; vm.items.rowData.push(itemRow); } itemRow.push(item); } vm.columns = newColumns; vm.topIndex = newTopIndex; vm.itemRows.getItemAtIndex(newTopIndex+pageSize); $timeout(function() { moveToIndex(newTopIndex); }, 500); } } function initGridConfiguration() { vm.gridConfiguration = vm.gridConfiguration || function () { return {}; }; vm.config = vm.gridConfiguration(); vm.itemHeight = vm.config.itemHeight || 199; vm.refreshParamsFunc = vm.config.refreshParamsFunc || function () { return {"topIndex": vm.topIndex}; }; vm.deleteItemTitleFunc = vm.config.deleteItemTitleFunc || function () { return $translate.instant('grid.delete-item-title'); }; vm.deleteItemContentFunc = vm.config.deleteItemContentFunc || function () { return $translate.instant('grid.delete-item-text'); }; vm.deleteItemsTitleFunc = vm.config.deleteItemsTitleFunc || function () { return $translate.instant('grid.delete-items-title', {count: vm.items.selectedCount}, 'messageformat'); }; vm.deleteItemsActionTitleFunc = vm.config.deleteItemsActionTitleFunc || function (selectedCount) { return $translate.instant('grid.delete-items-action-title', {count: selectedCount}, 'messageformat'); }; vm.deleteItemsContentFunc = vm.config.deleteItemsContentFunc || function () { return $translate.instant('grid.delete-items-text'); }; vm.fetchItemsFunc = vm.config.fetchItemsFunc || function () { return $q.when([]); }; vm.saveItemFunc = vm.config.saveItemFunc || function (item) { return $q.when(item); }; vm.deleteItemFunc = vm.config.deleteItemFunc || function () { return $q.when(); }; vm.clickItemFunc = vm.config.clickItemFunc || function ($event, item) { vm.openItem($event, item); }; vm.itemCardTemplate = ''; if (vm.config.itemCardTemplate) { vm.itemCardTemplate = vm.config.itemCardTemplate; } else if (vm.config.itemCardTemplateUrl) { vm.itemCardTemplate = $templateCache.get(vm.config.itemCardTemplateUrl); } vm.parentCtl = vm.config.parentCtl || vm; vm.getItemTitleFunc = vm.config.getItemTitleFunc || function () { return ''; }; vm.actionsList = vm.config.actionsList || []; for (var i = 0; i < vm.actionsList.length; i++) { var action = vm.actionsList[i]; action.isEnabled = action.isEnabled || function() { return true; }; } vm.groupActionsList = vm.config.groupActionsList || [ { onAction: function ($event) { deleteItems($event); }, name: function() { return $translate.instant('action.delete') }, details: vm.deleteItemsActionTitleFunc, icon: "delete" } ]; vm.addItemText = vm.config.addItemText || function () { return $translate.instant('grid.add-item-text'); }; vm.addItemAction = vm.config.addItemAction || { onAction: function ($event) { addItem($event); }, name: function() { return $translate.instant('action.add') }, details: function() { return vm.addItemText() }, icon: "add" }; vm.addItemActionsOpen = false; vm.addItemActions = vm.config.addItemActions || []; vm.onGridInited = vm.config.onGridInited || function () { }; vm.addItemTemplateUrl = vm.config.addItemTemplateUrl; vm.noItemsText = vm.config.noItemsText || function () { return $translate.instant('grid.no-items-text'); }; vm.itemDetailsText = vm.config.itemDetailsText || function () { return $translate.instant('grid.item-details'); }; vm.isDetailsReadOnly = vm.config.isDetailsReadOnly || function () { return false; }; vm.isSelectionEnabled = vm.config.isSelectionEnabled || function () { return true; }; vm.topIndex = vm.config.topIndex || 0; vm.items = vm.config.items || { data: [], rowData: [], nextPageLink: { limit: vm.topIndex + pageSize, textSearch: $scope.searchConfig.searchText }, selections: {}, selectedCount: 0, hasNext: true, pending: false }; vm.detailsConfig = { isDetailsOpen: false, isDetailsEditMode: false, currentItem: null, editingItem: null }; } $scope.$on('searchTextUpdated', function () { vm.items = { data: [], rowData: [], nextPageLink: { limit: pageSize, textSearch: $scope.searchConfig.searchText }, selections: {}, selectedCount: 0, hasNext: true, pending: false }; vm.detailsConfig.isDetailsOpen = false; vm.itemRows.getItemAtIndex(pageSize); }); vm.onGridInited(vm); vm.itemRows.getItemAtIndex(pageSize); function refreshList() { $state.go($state.current, vm.refreshParamsFunc(), {reload: true}); } function addItem($event) { $mdDialog.show({ controller: AddItemController, controllerAs: 'vm', templateUrl: vm.addItemTemplateUrl, parent: angular.element($document[0].body), locals: {saveItemFunction: vm.saveItemFunc}, fullscreen: true, targetEvent: $event }).then(function () { refreshList(); }, function () { }); } function openItem($event, item) { $event.stopPropagation(); if (vm.detailsConfig.currentItem != null && vm.detailsConfig.currentItem.id.id === item.id.id) { if (vm.detailsConfig.isDetailsOpen) { vm.detailsConfig.isDetailsOpen = false; return; } } vm.detailsConfig.currentItem = item; vm.detailsConfig.isDetailsEditMode = false; vm.detailsConfig.isDetailsOpen = true; } function isCurrentItem(item) { if (item != null && vm.detailsConfig.currentItem != null && vm.detailsConfig.currentItem.id.id === item.id.id) { return vm.detailsConfig.isDetailsOpen; } else { return false; } } function onToggleDetailsEditMode(theForm) { if (!vm.detailsConfig.isDetailsEditMode) { theForm.$setPristine(); } } function onCloseDetails() { vm.detailsConfig.currentItem = null; } function operatingItem() { if (!vm.detailsConfig.isDetailsEditMode) { if (vm.detailsConfig.editingItem) { vm.detailsConfig.editingItem = null; } return vm.detailsConfig.currentItem; } else { if (!vm.detailsConfig.editingItem) { vm.detailsConfig.editingItem = angular.copy(vm.detailsConfig.currentItem); } return vm.detailsConfig.editingItem; } } function saveItem(theForm) { vm.saveItemFunc(vm.detailsConfig.editingItem).then(function success(item) { theForm.$setPristine(); vm.detailsConfig.isDetailsEditMode = false; var index = vm.detailsConfig.currentItem.index; item.index = index; vm.detailsConfig.currentItem = item; vm.items.data[index] = item; var row = Math.floor(index / vm.columns); var itemRow = vm.items.rowData[row]; var column = index % vm.columns; itemRow[column] = item; }); } function deleteItem($event, item) { if ($event) { $event.stopPropagation(); } var confirm = $mdDialog.confirm() .targetEvent($event) .title(vm.deleteItemTitleFunc(item)) .htmlContent(vm.deleteItemContentFunc(item)) .ariaLabel($translate.instant('grid.delete-item')) .cancel($translate.instant('action.no')) .ok($translate.instant('action.yes')); $mdDialog.show(confirm).then(function () { vm.deleteItemFunc(item.id.id).then(function success() { refreshList(); }); }, function () { }); } function deleteItems($event) { var confirm = $mdDialog.confirm() .targetEvent($event) .title(vm.deleteItemsTitleFunc(vm.items.selectedCount)) .htmlContent(vm.deleteItemsContentFunc()) .ariaLabel($translate.instant('grid.delete-items')) .cancel($translate.instant('action.no')) .ok($translate.instant('action.yes')); $mdDialog.show(confirm).then(function () { var tasks = []; for (var id in vm.items.selections) { tasks.push(vm.deleteItemFunc(id)); } $q.all(tasks).then(function () { refreshList(); }); }, function () { }); } function toggleItemSelection($event, item) { $event.stopPropagation(); var selected = angular.isDefined(item.selected) && item.selected; item.selected = !selected; if (item.selected) { vm.items.selections[item.id.id] = true; vm.items.selectedCount++; } else { delete vm.items.selections[item.id.id]; vm.items.selectedCount--; } } function moveToTop() { moveToIndex(0, true); } function moveToIndex(index, animate) { var repeatContainer = $scope.repeatContainer[0]; var scrollElement = repeatContainer.children[0]; var startY = scrollElement.scrollTop; var stopY = index * vm.itemHeight; if (stopY > 0) { stopY+= 16; } var distance = Math.abs(startY - stopY); if (distance < 100 || !animate) { scrollElement.scrollTop = stopY; return; } var upElseDown = stopY < startY; var speed = Math.round(distance / 100); if (speed >= 20) speed = 20; var step = Math.round(distance / 25); var leapY = upElseDown ? startY - step : startY + step; var timer = 0; for (var i = startY; upElseDown ? (i > stopY) : (i < stopY); upElseDown ? (i -= step) : (i += step)) { $timeout(function (topY) { scrollElement.scrollTop = topY; }, timer * speed, true, leapY); if (upElseDown) { leapY -= step; if (leapY < stopY) { leapY = stopY; } } else { leapY += step; if (leapY > stopY) { leapY = stopY; } } timer++; } } function noData() { return vm.items.data.length == 0 && !vm.items.hasNext; } function hasData() { return vm.items.data.length > 0; } } /*@ngInject*/ function AddItemController($scope, $mdDialog, saveItemFunction, helpLinks) { var vm = this; vm.helpLinks = helpLinks; vm.item = {}; vm.add = add; vm.cancel = cancel; function cancel() { $mdDialog.cancel(); } function add() { saveItemFunction(vm.item).then(function success(item) { vm.item = item; $scope.theForm.$setPristine(); $mdDialog.hide(); }); } }