diff --git a/ui/package.json b/ui/package.json index 5f00611bff..ddcc96e4f7 100644 --- a/ui/package.json +++ b/ui/package.json @@ -33,6 +33,7 @@ "angular-messages": "1.5.8", "angular-route": "1.5.8", "angular-sanitize": "1.5.8", + "angular-socialshare": "^2.3.8", "angular-storage": "0.0.15", "angular-touch": "1.5.8", "angular-translate": "2.13.1", diff --git a/ui/src/app/app.js b/ui/src/app/app.js index e3b36e3c6b..290e9cdf1c 100644 --- a/ui/src/app/app.js +++ b/ui/src/app/app.js @@ -19,6 +19,7 @@ import angular from 'angular'; import ngMaterial from 'angular-material'; import ngMdIcons from 'angular-material-icons'; import ngCookies from 'angular-cookies'; +import angularSocialshare from 'angular-socialshare'; import 'angular-translate'; import 'angular-translate-loader-static-files'; import 'angular-translate-storage-local'; @@ -82,6 +83,7 @@ angular.module('thingsboard', [ ngMaterial, ngMdIcons, ngCookies, + angularSocialshare, 'pascalprecht.translate', 'mdColorPicker', mdPickers, diff --git a/ui/src/app/common/utils.service.js b/ui/src/app/common/utils.service.js index 09d0fc894b..6e05bbbf6c 100644 --- a/ui/src/app/common/utils.service.js +++ b/ui/src/app/common/utils.service.js @@ -106,7 +106,8 @@ function Utils($mdColorPalette, $rootScope, $window, $q, deviceService, types) { isDescriptorSchemaNotEmpty: isDescriptorSchemaNotEmpty, filterSearchTextEntities: filterSearchTextEntities, guid: guid, - createDatasoucesFromSubscriptionsInfo: createDatasoucesFromSubscriptionsInfo + createDatasoucesFromSubscriptionsInfo: createDatasoucesFromSubscriptionsInfo, + isLocalUrl: isLocalUrl } return service; @@ -428,4 +429,15 @@ function Utils($mdColorPalette, $rootScope, $window, $q, deviceService, types) { return deferred.promise; } + function isLocalUrl(url) { + var parser = document.createElement('a'); //eslint-disable-line + parser.href = url; + var host = parser.hostname; + if (host === "localhost" || host === "127.0.0.1") { + return true; + } else { + return false; + } + } + } diff --git a/ui/src/app/components/socialshare-panel.directive.js b/ui/src/app/components/socialshare-panel.directive.js new file mode 100644 index 0000000000..891d91368e --- /dev/null +++ b/ui/src/app/components/socialshare-panel.directive.js @@ -0,0 +1,58 @@ +/* + * 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. + */ + +/* eslint-disable import/no-unresolved, import/default */ + +import socialsharePanelTemplate from './socialshare-panel.tpl.html'; + +/* eslint-enable import/no-unresolved, import/default */ + + +export default angular.module('thingsboard.directives.socialsharePanel', []) + .directive('tbSocialSharePanel', SocialsharePanel) + .name; + +/*@ngInject*/ +function SocialsharePanel() { + return { + restrict: "E", + scope: true, + bindToController: { + shareTitle: '@', + shareText: '@', + shareLink: '@', + shareHashTags: '@' + }, + controller: SocialsharePanelController, + controllerAs: 'vm', + templateUrl: socialsharePanelTemplate + }; +} + +/*@ngInject*/ +function SocialsharePanelController(utils) { + + let vm = this; + + vm.isShareLinkLocal = function() { + if (vm.shareLink && vm.shareLink.length > 0) { + return utils.isLocalUrl(vm.shareLink); + } else { + return true; + } + } + +} \ No newline at end of file diff --git a/ui/src/app/components/socialshare-panel.tpl.html b/ui/src/app/components/socialshare-panel.tpl.html new file mode 100644 index 0000000000..7b9560de36 --- /dev/null +++ b/ui/src/app/components/socialshare-panel.tpl.html @@ -0,0 +1,62 @@ + + +
+ + + + {{ 'action.share-via' | translate:{provider:'Facebook'} }} + + + + + + {{ 'action.share-via' | translate:{provider:'Twitter'} }} + + + + + + {{ 'action.share-via' | translate:{provider:'Linkedin'} }} + + + + + + {{ 'action.share-via' | translate:{provider:'Reddit'} }} + + +
\ No newline at end of file diff --git a/ui/src/app/dashboard/dashboard-fieldset.tpl.html b/ui/src/app/dashboard/dashboard-fieldset.tpl.html index 1d11fb2c60..954d881588 100644 --- a/ui/src/app/dashboard/dashboard-fieldset.tpl.html +++ b/ui/src/app/dashboard/dashboard-fieldset.tpl.html @@ -36,20 +36,28 @@ -
- - - - - - - - {{ 'dashboard.copy-public-link' | translate }} - - +
+ + +
+ + + + + + + + {{ 'dashboard.copy-public-link' | translate }} + + +
diff --git a/ui/src/app/dashboard/dashboard-settings.controller.js b/ui/src/app/dashboard/dashboard-settings.controller.js index aac6da3dd0..06c64eb757 100644 --- a/ui/src/app/dashboard/dashboard-settings.controller.js +++ b/ui/src/app/dashboard/dashboard-settings.controller.js @@ -31,6 +31,18 @@ export default function DashboardSettingsController($scope, $mdDialog, gridSetti vm.gridSettings.showTitle = true; } + if (angular.isUndefined(vm.gridSettings.showDevicesSelect)) { + vm.gridSettings.showDevicesSelect = true; + } + + if (angular.isUndefined(vm.gridSettings.showDashboardTimewindow)) { + vm.gridSettings.showDashboardTimewindow = true; + } + + if (angular.isUndefined(vm.gridSettings.showDashboardExport)) { + vm.gridSettings.showDashboardExport = true; + } + vm.gridSettings.backgroundColor = vm.gridSettings.backgroundColor || 'rgba(0,0,0,0)'; vm.gridSettings.titleColor = vm.gridSettings.titleColor || 'rgba(0,0,0,0.870588)'; vm.gridSettings.columns = vm.gridSettings.columns || 24; diff --git a/ui/src/app/dashboard/dashboard-settings.tpl.html b/ui/src/app/dashboard/dashboard-settings.tpl.html index 2ed25d3edf..ec6f28b369 100644 --- a/ui/src/app/dashboard/dashboard-settings.tpl.html +++ b/ui/src/app/dashboard/dashboard-settings.tpl.html @@ -48,6 +48,17 @@ md-color-history="false" >
+
+ {{ 'dashboard.display-device-selection' | translate }} + + {{ 'dashboard.display-dashboard-timewindow' | translate }} + + {{ 'dashboard.display-dashboard-export' | translate }} + +
- {{ 'dashboard.export' | translate }} file_download - + - @@ -304,6 +309,6 @@ diff --git a/ui/src/app/dashboard/dashboards.controller.js b/ui/src/app/dashboard/dashboards.controller.js index d0fa95860c..134baffc59 100644 --- a/ui/src/app/dashboard/dashboards.controller.js +++ b/ui/src/app/dashboard/dashboards.controller.js @@ -224,7 +224,7 @@ export function DashboardsController(userService, dashboardService, customerServ onAction: function ($event, item) { unassignFromCustomer($event, item, true); }, - name: function() { return $translate.instant('action.unshare') }, + name: function() { return $translate.instant('action.make-private') }, details: function() { return $translate.instant('dashboard.make-private') }, icon: "reply", isEnabled: function(dashboard) { @@ -329,7 +329,7 @@ export function DashboardsController(userService, dashboardService, customerServ onAction: function ($event, item) { unassignFromCustomer($event, item, true); }, - name: function() { return $translate.instant('action.unshare') }, + name: function() { return $translate.instant('action.make-private') }, details: function() { return $translate.instant('dashboard.make-private') }, icon: "reply", isEnabled: function(dashboard) { @@ -404,7 +404,28 @@ export function DashboardsController(userService, dashboardService, customerServ } function saveDashboard(dashboard) { - return dashboardService.saveDashboard(dashboard); + var deferred = $q.defer(); + dashboardService.saveDashboard(dashboard).then( + function success(savedDashboard) { + var dashboards = [ savedDashboard ]; + customerService.applyAssignedCustomersInfo(dashboards).then( + function success(items) { + if (items && items.length == 1) { + deferred.resolve(items[0]); + } else { + deferred.reject(); + } + }, + function fail() { + deferred.reject(); + } + ); + }, + function fail() { + deferred.reject(); + } + ); + return deferred.promise; } function assignToCustomer($event, dashboardIds) { diff --git a/ui/src/app/dashboard/index.js b/ui/src/app/dashboard/index.js index 4587001281..88d71fb0e2 100644 --- a/ui/src/app/dashboard/index.js +++ b/ui/src/app/dashboard/index.js @@ -30,6 +30,7 @@ import thingsboardDashboardSelect from '../components/dashboard-select.directive import thingsboardDashboard from '../components/dashboard.directive'; import thingsboardExpandFullscreen from '../components/expand-fullscreen.directive'; import thingsboardWidgetsBundleSelect from '../components/widgets-bundle-select.directive'; +import thingsboardSocialsharePanel from '../components/socialshare-panel.directive'; import thingsboardTypes from '../common/types.constant'; import thingsboardItemBuffer from '../services/item-buffer.service'; import thingsboardImportExport from '../import-export'; @@ -64,7 +65,8 @@ export default angular.module('thingsboard.dashboard', [ thingsboardDashboardSelect, thingsboardDashboard, thingsboardExpandFullscreen, - thingsboardWidgetsBundleSelect + thingsboardWidgetsBundleSelect, + thingsboardSocialsharePanel ]) .config(DashboardRoutes) .controller('DashboardsController', DashboardsController) diff --git a/ui/src/app/dashboard/make-dashboard-public-dialog.tpl.html b/ui/src/app/dashboard/make-dashboard-public-dialog.tpl.html index 31f49fbc34..8d96b30225 100644 --- a/ui/src/app/dashboard/make-dashboard-public-dialog.tpl.html +++ b/ui/src/app/dashboard/make-dashboard-public-dialog.tpl.html @@ -43,6 +43,12 @@
dashboard.public-dashboard-notice
+ + diff --git a/ui/src/app/device/device.controller.js b/ui/src/app/device/device.controller.js index ed9ff6ff8c..55b70832e2 100644 --- a/ui/src/app/device/device.controller.js +++ b/ui/src/app/device/device.controller.js @@ -185,7 +185,7 @@ export function DeviceController(userService, deviceService, customerService, $s onAction: function ($event, item) { unassignFromCustomer($event, item, true); }, - name: function() { return $translate.instant('action.unshare') }, + name: function() { return $translate.instant('action.make-private') }, details: function() { return $translate.instant('device.make-private') }, icon: "reply", isEnabled: function(device) { @@ -271,7 +271,7 @@ export function DeviceController(userService, deviceService, customerService, $s onAction: function ($event, item) { unassignFromCustomer($event, item, true); }, - name: function() { return $translate.instant('action.unshare') }, + name: function() { return $translate.instant('action.make-private') }, details: function() { return $translate.instant('device.make-private') }, icon: "reply", isEnabled: function(device) { @@ -364,8 +364,29 @@ export function DeviceController(userService, deviceService, customerService, $s return device ? device.name : ''; } - function saveDevice (device) { - return deviceService.saveDevice(device); + function saveDevice(device) { + var deferred = $q.defer(); + deviceService.saveDevice(device).then( + function success(savedDevice) { + var devices = [ savedDevice ]; + customerService.applyAssignedCustomersInfo(devices).then( + function success(items) { + if (items && items.length == 1) { + deferred.resolve(items[0]); + } else { + deferred.reject(); + } + }, + function fail() { + deferred.reject(); + } + ); + }, + function fail() { + deferred.reject(); + } + ); + return deferred.promise; } function isCustomerUser() { diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js index 37a2b93b48..32b422bca0 100644 --- a/ui/src/app/locale/locale.constant.js +++ b/ui/src/app/locale/locale.constant.js @@ -44,7 +44,7 @@ export default angular.module('thingsboard.locale', []) "assign": "Assign", "unassign": "Unassign", "share": "Share", - "unshare": "Unshare", + "make-private": "Make private", "apply": "Apply", "apply-changes": "Apply changes", "edit-mode": "Edit mode", @@ -63,7 +63,8 @@ export default angular.module('thingsboard.locale', []) "copy": "Copy", "paste": "Paste", "import": "Import", - "export": "Export" + "export": "Export", + "share-via": "Share via {{provider}}" }, "aggregation": { "aggregation": "Aggregation", @@ -233,6 +234,8 @@ export default angular.module('thingsboard.locale', []) "make-private-dashboard-title": "Are you sure you want to make the dashboard '{{dashboardTitle}}' private?", "make-private-dashboard-text": "After the confirmation the dashboard will be made private and won't be accessible by others.", "make-private-dashboard": "Make dashboard private", + "socialshare-text": "'{{dashboardTitle}}' powered by ThingsBoard", + "socialshare-title": "'{{dashboardTitle}}' powered by ThingsBoard", "select-dashboard": "Select dashboard", "no-dashboards-matching": "No dashboards matching '{{dashboard}}' were found.", "dashboard-required": "Dashboard is required.", @@ -262,6 +265,9 @@ export default angular.module('thingsboard.locale', []) "max-vertical-margin-message": "Only 50 is allowed as maximum vertical margin value.", "display-title": "Display dashboard title", "title-color": "Title color", + "display-device-selection": "Display device selection", + "display-dashboard-timewindow": "Display timewindow", + "display-dashboard-export": "Display export", "import": "Import dashboard", "export": "Export dashboard", "export-failed-error": "Unable to export dashboard: {{error}}", diff --git a/ui/webpack.config.dev.js b/ui/webpack.config.dev.js index c669ec5b22..fa019d3292 100644 --- a/ui/webpack.config.dev.js +++ b/ui/webpack.config.dev.js @@ -60,6 +60,7 @@ module.exports = { allChunks: true, }), new webpack.DefinePlugin({ + THINGSBOARD_VERSION: JSON.stringify(require('./package.json').version), '__DEVTOOLS__': false, 'process.env': { NODE_ENV: JSON.stringify('development'), diff --git a/ui/webpack.config.prod.js b/ui/webpack.config.prod.js index 09374fb6a5..a746488850 100644 --- a/ui/webpack.config.prod.js +++ b/ui/webpack.config.prod.js @@ -58,6 +58,7 @@ module.exports = { allChunks: true, }), new webpack.DefinePlugin({ + THINGSBOARD_VERSION: JSON.stringify(require('./package.json').version), '__DEVTOOLS__': false, 'process.env': { NODE_ENV: JSON.stringify('production'),