From bc4b0328fb9e7d1f539ede0b874aba475a4c8f0d Mon Sep 17 00:00:00 2001 From: Dave Bauman Date: Thu, 23 Jun 2016 07:10:47 -0700 Subject: [PATCH] 1.33.0 release --- CHANGELOG.md | 6 + cyclotron-site/app/partials/dashboard.jade | 3 +- .../app/partials/help/javascriptApi.jade | 117 ++++++++++++++++++ cyclotron-site/app/partials/widgetError.jade | 4 +- cyclotron-site/app/scripts/common/app.coffee | 3 + .../services.commonConfigService.coffee | 17 ++- .../dashboards/controller.dashboard.coffee | 34 ++++- .../directives.dashboardPage.coffee | 31 +++-- .../directives.dashboardWidget.coffee | 3 - .../directives/directives.widget.coffee | 103 +++++++++++---- .../directives/directives.widgetBody.coffee | 4 +- .../directives/directives.widgetError.coffee | 15 ++- .../services/services.dataService.coffee | 5 +- .../services/services.parameterService.coffee | 2 +- .../app/scripts/mgmt/controller.help.coffee | 5 +- .../directives/directives.collapseMenu.coffee | 27 ++-- cyclotron-site/app/widgets/clock/clock.jade | 2 +- .../app/widgets/table/tableWidget.coffee | 2 +- 18 files changed, 311 insertions(+), 72 deletions(-) create mode 100644 cyclotron-site/app/partials/help/javascriptApi.jade diff --git a/CHANGELOG.md b/CHANGELOG.md index 203a394..1737bc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 1.33.0 (06/23/2016) + +## Features + + - JavaScript API for hiding/showing Widgets: Added API for changing the visibility of Widgets at runtime. Changes to Widget visibility is remembered across sessions by the user's browser. + # 1.32.0 (06/09/2016) ## Features diff --git a/cyclotron-site/app/partials/dashboard.jade b/cyclotron-site/app/partials/dashboard.jade index 11a4636..70ad369 100644 --- a/cyclotron-site/app/partials/dashboard.jade +++ b/cyclotron-site/app/partials/dashboard.jade @@ -12,6 +12,7 @@ div.dashboard i.fa.fa-chevron-right(ng-click='moveForward()', ng-class='{ disabled: !canMoveForward() }', title='Go to the next page') .dashboard-pages - div(dashboard-page, dashboard='dashboard', page='page', page-number='{{ currentPageIndex }}', + div(dashboard-page, dashboard='dashboard', + page='page', page-number='{{ currentPageIndex }}', page-overrides='dashboardOverrides.pages[currentPageIndex]', ng-repeat='page in currentPage') diff --git a/cyclotron-site/app/partials/help/javascriptApi.jade b/cyclotron-site/app/partials/help/javascriptApi.jade new file mode 100644 index 0000000..21ac99d --- /dev/null +++ b/cyclotron-site/app/partials/help/javascriptApi.jade @@ -0,0 +1,117 @@ +h3 JavaScript API + +p. + Cyclotron provides a JavaScript API that Dashboards can leverage. They make it easier to extend Cyclotron with custom functionality and add additional interactivity to a Dashboard. Basically, it exposes various actions in the Dashboard (e.g. execute a Data Source, show/hide a Widget), or to provide information about the Dashboard. + +p + | In addition to the Cyclotron API, there are a handful of 3rd party JavaScript libraries which are bundled with Cyclotron. Theese are the libraries that Cyclotron itself is built on, making them available for use by Dashboards as well. More information about these libraries can be found at + a(ng-click='findItem("3rd Party Libraries")', href='?q=3rd Party Libraries') 3rd Party Libraries + +h4 Dashboard Information + +table + tr + th Method/Property + th Description + tr + td Cyclotron.version + td Property that returns the current version of Cyclotron + tr + td Cyclotron.dashboard + td Property that returns the current Dashboard as an object + tr + td Cyclotron.dashboardOverrides + td Property that returns an object of user-specific overrides for the current Dashboard + tr + td Cyclotron.dashboardName + td Property that returns the name of the current Dashboard + tr + td Cyclotron.pageName + td Property that returns the name of the currently-displayed Page + tr + td Cyclotron.goToPage(pageNumber) + td Navigates to a specific page in the Dashboard (starting with page 1) + tr + td Cyclotron.getDeeplink() + td Returns a deeplink URL to the current Dashboard, including the values of all Parameters + +h4 Built-In Parameters + +p These Parameters are built-in to every Dashboard, and appear in the URL when set. They don't have to be configured manually in the Parameters section of the Dashboard, but they can be added there in order to change the default value. + +table + tr + th Parameter + th Description + tr + td Cyclotron.parameters.page + td Set to the current page number (as an integer) + tr + td Cyclotron.parameters.rev + td Set to the Dashboard's revision number (as a string); this will be undefined when viewing the latest revision + tr + td Cyclotron.parameters.live + td If true, causes the Dashboard to check for new Revisions more frequently. This Parameter can be set via URL only, when the Dashboard is loaded. + tr + td Cyclotron.parameters.autoRotate + td True/false value that enables/disables rotation in the Dashboard, overriding the Dashboard's setting. This Parameter can be set via URL only, when the Dashboard is loaded. + +h4 Data Sources + +p These functions allow interaction with the Data Sources in the Dashboard. The + em Cyclotron.dataSource + | object contains each Data Source name as a key, with an object of functions as the value. + +table + tr + th Method + th Description + tr + td Cyclotron.dataSources['dataSourceName'].execute([showSpinners]) + td Manually executes a Data Source. If showSpinners is true, it will triggers Widgets to show a loading spinner while the Data Source is executing + tr + td Cyclotron.dataSources['dataSourceName'].getPromise() + td Returns the latest execution promise (may be completed). The returned promise has two functions, promise.then(function) and promise.catch(function). If the Data Source has already completed, then() will execute the given function immediately. This function returns an object of resultsets, each containing columns (optional) and data. + tr + td Cyclotron.dataSources['dataSourceName'].getCachedDataSet([resultSetName]) + td Returns the latest resultset for the Data Source if it exists, else null. If no resultSet argument is provided, the default resultset name of '0' will be used. This function returns the result set data directly. + tr + td Cyclotron.dataSources['dataSourceName'].getData() + td Deprecated; do not use + tr + td Cyclotron.dataSources['dataSourceName'].init() + td Initializes the Data Source and starts automatic refresh if configured. This method is used internally by Widgets; execute() is probably better suited to custom JavaScript scripting. + +h4 Widgets + +p These functions apply overrides to Widgets in the Dashboard. In order to use these functions, the Widget needs to have the + em name + | property configured; the + em Cyclotron.currentPage.widgets + | object contains each Widget name as a key, with an object of functions as the value. + +table + tr + th Method + th Description + tr + td Cyclotron.currentPage.widgets['widgetName'].show() + td Shows a Widget; overrides the Widget's + em hidden + | property + tr + td Cyclotron.currentPage.widgets['widgetName'].hide() + td Hides a Widget; overrides the Widget's + em hidden + | property + tr + td Cyclotron.currentPage.widgets['widgetName'].toggleVisibility() + td Toggles the visibility of a Widget; overrides the Widget's + em hidden + | property + +h4 CyclotronData + +p CyclotronData has a JavaScript API for reading/writing data. This is documented separately on the + a(ng-click='findItem("CyclotronData")', href='?q=CyclotronData') CyclotronData + | page. diff --git a/cyclotron-site/app/partials/widgetError.jade b/cyclotron-site/app/partials/widgetError.jade index 8ea6b89..d6b6303 100644 --- a/cyclotron-site/app/partials/widgetError.jade +++ b/cyclotron-site/app/partials/widgetError.jade @@ -1,8 +1,8 @@ .widget-error-container - .fa.fa-exclamation(title='{{ dataSourceErrorMessage }}') + .fa.fa-exclamation(title='{{ errorMessage }}') .widget-reload(ng-click='reload()') i.fa.fa-refresh | Reload - .widget-error-message(title='{{ dataSourceErrorMessage }}') + .widget-error-message(title='{{ errorMessage }}') | {{ shortErrorMessage }} diff --git a/cyclotron-site/app/scripts/common/app.coffee b/cyclotron-site/app/scripts/common/app.coffee index c97b11e..92d161c 100644 --- a/cyclotron-site/app/scripts/common/app.coffee +++ b/cyclotron-site/app/scripts/common/app.coffee @@ -59,6 +59,9 @@ cyclotronServices = angular.module 'cyclotronApp.services', ['ngResource'] cyclotronApp.config ($stateProvider, $urlRouterProvider, $locationProvider, $controllerProvider, $compileProvider, $provide, uiSelectConfig) -> + # Improve performance + $compileProvider.debugInfoEnabled false + uiSelectConfig.theme = 'select2' # Save some providers for later diff --git a/cyclotron-site/app/scripts/common/services/services.commonConfigService.coffee b/cyclotron-site/app/scripts/common/services/services.commonConfigService.coffee index 8dca836..0cc5b98 100644 --- a/cyclotron-site/app/scripts/common/services/services.commonConfigService.coffee +++ b/cyclotron-site/app/scripts/common/services/services.commonConfigService.coffee @@ -26,7 +26,7 @@ cyclotronServices.factory 'commonConfigService', -> exports = { - version: '1.32.0' + version: '1.33.0' logging: enableDebug: false @@ -1088,6 +1088,11 @@ cyclotronServices.factory 'commonConfigService', -> path: '/partials/help/examples.html' tags: ['examples', 'cyclotron-examples'] } + { + name: 'Browser Compatibility' + path: '/partials/help/browserCompat.html' + tags: ['browser', 'compatibility', 'firefox', 'chrome', 'internet explorer', 'ie', 'safari', 'browsercheck'] + } { name: 'Permissions' path: '/partials/help/permissions.html' @@ -1098,16 +1103,16 @@ cyclotronServices.factory 'commonConfigService', -> path: '/partials/help/encryptedStrings.html' tags: ['encryption', 'encrypted', '!{', 'decrypt', 'encrypt'] } + { + name: 'JavaScript API' + path: '/partials/help/javascriptApi.html' + tags: ['javascript', 'api', 'scripting'] + } { name: 'CyclotronData' path: '/partials/help/cyclotrondata.html' tags: ['cyclotrondata', 'data', 'storage', 'bucket', 'api'] } - { - name: 'Browser Compatibility' - path: '/partials/help/browserCompat.html' - tags: ['browser', 'compatibility', 'firefox', 'chrome', 'internet explorer', 'ie', 'safari', 'browsercheck'] - } { name: '3rd Party Libraries' path: '/partials/help/3rdparty.html' diff --git a/cyclotron-site/app/scripts/dashboards/controller.dashboard.coffee b/cyclotron-site/app/scripts/dashboards/controller.dashboard.coffee index de412bd..18f1f5c 100644 --- a/cyclotron-site/app/scripts/dashboards/controller.dashboard.coffee +++ b/cyclotron-site/app/scripts/dashboards/controller.dashboard.coffee @@ -17,7 +17,7 @@ # # Home controller. # -cyclotronApp.controller 'DashboardController', ($scope, $stateParams, $location, $timeout, $window, $q, $uibModal, analyticsService, configService, cyclotronDataService, dashboardService, dataService, loadService, logService, parameterService, userService) -> +cyclotronApp.controller 'DashboardController', ($scope, $stateParams, $localForage, $location, $timeout, $window, $q, $uibModal, analyticsService, configService, cyclotronDataService, dashboardService, dataService, loadService, logService, parameterService, userService) -> preloadTimer = null rotateTimer = null @@ -101,6 +101,9 @@ cyclotronApp.controller 'DashboardController', ($scope, $stateParams, $location, $scope.updateUrl() + $window.Cyclotron.currentPage = + widgets: {} + # Track analytics analyticsService.recordPageView $scope.dashboardWrapper, $scope.currentPageIndex, $scope.firstLoad @@ -285,18 +288,32 @@ cyclotronApp.controller 'DashboardController', ($scope, $stateParams, $location, dashboardService.setDashboardDefaults(dashboard) $scope.dashboard = dashboard + # Initialize dashboard overrides + $scope.dashboardOverrides.pages ?= [] + _.each dashboard.pages, (page, index) -> + if !$scope.dashboardOverrides.pages[index]? + $scope.dashboardOverrides.pages.push { widgets: [] } + $scope.dashboardOverrides.pages[index].widgets ?= [] + _.each page.widgets, (widget, widgetIndex) -> + if !$scope.dashboardOverrides.pages[index].widgets[widgetIndex]? + $scope.dashboardOverrides.pages[index].widgets.push {} + # Optionally disable analytics if dashboard.disableAnalytics == true configService.enableAnalytics = false dependenciesLoaded = -> - # Update current page if needed - if $scope.currentPage? + # Check if a new revision of the Dashboard has been loaded + if $scope.latestRevision and $scope.latestRevision < $scope.dashboardWrapper.rev + # Update current page if needed originalPage = $scope.currentPage[$scope.currentPage.length-1] newPage = $scope.dashboard.pages[$scope.currentPageIndex] if !angular.equals(originalPage, newPage) + logService.debug 'Replacing the current page with a new revision' $scope.currentPage[$scope.currentPage.length-1] = newPage + $scope.latestRevision = $scope.dashboardWrapper.rev + # Resolve promise deferred.resolve() @@ -389,7 +406,7 @@ cyclotronApp.controller 'DashboardController', ($scope, $stateParams, $location, _.each themes, (theme) -> loadService.loadCssUrl('/css/app.themes.' + theme + '.css', true) - # Intialize parameters + # Initialize parameters parameterService.initializeParameters($scope.dashboard).then -> # Watch querystring for changes @@ -449,7 +466,14 @@ cyclotronApp.controller 'DashboardController', ($scope, $stateParams, $location, .search $scope.deeplinkOptions .toString() - $scope.loadDashboard().then $scope.initialLoad + # Load Overrides, then the dashboard + $localForage.bind($scope, { + key: 'dashboardOverrides' + defaultValue: { pages: [] } + }).then -> + $window.Cyclotron.dashboardOverrides = $scope.dashboardOverrides + logService.debug 'Dashboard Overrides: ' + JSON.stringify($scope.dashboardOverrides) + $scope.loadDashboard().then $scope.initialLoad # # Hot Key Bindings diff --git a/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardPage.coffee b/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardPage.coffee index b28a879..dfe6437 100644 --- a/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardPage.coffee +++ b/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardPage.coffee @@ -1,5 +1,5 @@ ### -# Copyright (c) 2013-2015 the original author or authors. +# Copyright (c) 2013-2016 the original author or authors. # # Licensed under the MIT License (the "License"); # you may not use this file except in compliance with the License. @@ -14,6 +14,16 @@ # language governing permissions and limitations under the License. ### +# +# Top-level Page directive +# +# Renders a series of Widgets and manages page-level interactivity. Expects the following +# scope variables: +# page: Page to render +# pageOverrides: Overrides for the current page +# pageNumber: Index of the Page in the Dashboard (zero-indexed) +# dashboard: Entire Dashboard object +# cyclotronDirectives.directive 'dashboardPage', ($compile, $window, $timeout, configService, layoutService, logService) -> { replace: true @@ -21,11 +31,14 @@ cyclotronDirectives.directive 'dashboardPage', ($compile, $window, $timeout, con scope: page: '=' + pageOverrides: '=' + pageNumber: '@' dashboard: '=' template: '
' + '
' + - '
' + + '
' + '
' link: (scope, element, attrs) -> @@ -107,21 +120,18 @@ cyclotronDirectives.directive 'dashboardPage', ($compile, $window, $timeout, con scope.postLayout = _.after newValue.widgets.length, -> if (newValue.enableMasonry != false) masonry(element, scope.layout) + return - newLayout = layoutService.getLayout(newValue, $($window).width(), $($window).height()) - - # Optional persistent widget area of layout - newLayout.widget = scope.layout?.widget || {} - scope.layout = newLayout + scope.layout = layoutService.getLayout(newValue, $($window).width(), $($window).height()) # Set page margin if defined if !_.isNullOrUndefined(scope.layout.margin) - $element.css('padding', scope.layout.margin + 'px') + $element.css 'padding', scope.layout.margin + 'px' - $dashboardPageInner.css({ + $dashboardPageInner.css { marginRight: '-' + scope.layout.gutter + 'px' marginBottom: '-' + scope.layout.gutter + 'px' - }) + } # Enable/disable scrolling of the dashboard page if !scope.layout.scrolling @@ -172,4 +182,5 @@ cyclotronDirectives.directive 'dashboardPage', ($compile, $window, $timeout, con $dashboardPageInner.masonry('destroy') return + } diff --git a/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardWidget.coffee b/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardWidget.coffee index 0d4bde5..898a387 100644 --- a/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardWidget.coffee +++ b/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardWidget.coffee @@ -24,9 +24,6 @@ cyclotronDirectives.directive 'dashboardWidget', (layoutService) -> scope.$watch 'widget', (widget) -> - # Ignore the widget if hidden is set - return if widget.hidden == true - # Wire-up fullscreen button if available if widget.allowFullscreen $parent.find('.widget-fullscreen').click -> diff --git a/cyclotron-site/app/scripts/dashboards/directives/directives.widget.coffee b/cyclotron-site/app/scripts/dashboards/directives/directives.widget.coffee index 97f7d54..b53defb 100644 --- a/cyclotron-site/app/scripts/dashboards/directives/directives.widget.coffee +++ b/cyclotron-site/app/scripts/dashboards/directives/directives.widget.coffee @@ -1,5 +1,5 @@ ### -# Copyright (c) 2013-2015 the original author or authors. +# Copyright (c) 2013-2016 the original author or authors. # # Licensed under the MIT License (the "License"); # you may not use this file except in compliance with the License. @@ -14,30 +14,77 @@ # language governing permissions and limitations under the License. ### -cyclotronDirectives.directive 'widget', ($compile, $sce, layoutService) -> +# +# Top-level Widget directive +# +# Dynamically renders the configured widget into itself. Expects the following +# scope variables: +# widget: Widget to render +# widgetIndex: Index of the widget in the current page (zero-indexed) +# layout: Page layout object +# dashboard: Entire Dashboard object +# pageOverrides: Overrides object for the current page only +# postLayout: Function to be called when the Widget has finished updating its layout +# +cyclotronDirectives.directive 'widget', ($compile, $sce, $window, layoutService) -> { restrict: 'A' + scope: + widget: '=' + widgetIndex: '=' + layout: '=' + dashboard: '=' + pageOverrides: '=' + postLayout: '&' link: (scope, element, attrs) -> $element = $(element) - # - # This directive dynamically replaces itself with the specified widget in the current scope - # - widget = null - layout = null - # Save the SCE handler in the scope scope.$sce = $sce - # Watch for the model to change, indicating this widget needs to be updated + scope.widgetLayout = { } + + # Determine if a Widget should be visible or hidden on the dashboard + isWidgetHidden = -> + return false unless scope.widget? + + if scope.pageOverrides?.widgets? + widgetOverrides = scope.pageOverrides.widgets?[scope.widgetIndex] + + # If WidgetOverrides.hidden is set true or false, use its value + if widgetOverrides?.hidden? + return widgetOverrides.hidden == true + + # Else, default to the widget's "hidden" property + return scope.widget.hidden == true + + # Store Widget API for use by Dashboards + if scope.widget.name? + $window.Cyclotron.currentPage.widgets[scope.widget.name] = { + show: -> + scope.$apply -> + widgetOverrides = scope.pageOverrides?.widgets?[scope.widgetIndex] + widgetOverrides.hidden = false + hide: -> + scope.$apply -> + widgetOverrides = scope.pageOverrides?.widgets?[scope.widgetIndex] + widgetOverrides.hidden = true + toggleVisibility: -> + scope.$apply -> + widgetOverrides = scope.pageOverrides?.widgets?[scope.widgetIndex] + widgetOverrides.hidden = !widgetOverrides.hidden + } + + # Watch for widget visibility to change + scope.$watch isWidgetHidden, (isHidden) -> + scope.layout.hidden = isHidden + + # Watch for the widget model to change, indicating this widget needs to be updated scope.$watch 'widget', (newValue, oldValue) -> widget = newValue - # Ignore the widget if hidden is set - return if widget.hidden == true - # Ignore widgets without a type return if _.isEmpty widget.widget @@ -60,10 +107,17 @@ cyclotronDirectives.directive 'widget', ($compile, $sce, layoutService) -> return + # Watch for page layout changes and resize the widget scope.$watch('layout', (layout, oldLayout) -> + + # Ensure a valid layout is provided + if _.isUndefined(layout) + return scope.postLayout() - # Ignore the widget if hidden is set - return scope.postLayout() if widget.hidden == true or _.isUndefined(layout) + if isWidgetHidden() + # Hide Widget to avoid occupying space + $element.css 'display', 'none' + return scope.postLayout() # Copy gridWidth/width into the scope # Apply overrides if necessary (mobile devices) @@ -74,27 +128,27 @@ cyclotronDirectives.directive 'widget', ($compile, $sce, layoutService) -> scope.widgetGridWidth = layout.forceGridWidth scope.widgetWidth = null else - scope.widgetGridWidth = widget.gridWidth - scope.widgetWidth = widget.width + scope.widgetGridWidth = scope.widget.gridWidth + scope.widgetWidth = scope.widget.width if layout.forceGridHeight? - if widget.gridHeight == layout.originalGridRows + if scope.widget.gridHeight == layout.originalGridRows scope.widgetGridHeight = layout.gridRows else scope.widgetGridHeight = layout.forceGridHeight scope.widgetHeight = null else - scope.widgetGridHeight = widget.gridHeight - scope.widgetHeight = widget.height + scope.widgetGridHeight = scope.widget.gridHeight + scope.widgetHeight = scope.widget.height # Calculate widget dimensions if scope.widgetHeight? - scope.widgetHeight = widget.height + scope.widgetHeight = scope.widget.height else if scope.widgetGridHeight? scope.widgetHeight = layout.gridSquareHeight * scope.widgetGridHeight + ((layout.gutter) * (scope.widgetGridHeight - 1)) if scope.widgetWidth? - scope.widgetWidth = widget.width + scope.widgetWidth = scope.widget.width else if scope.widgetGridWidth? scope.widgetWidth = layout.gridSquareWidth * scope.widgetGridWidth + (layout.gutter * (scope.widgetGridWidth - 1)) else @@ -103,11 +157,12 @@ cyclotronDirectives.directive 'widget', ($compile, $sce, layoutService) -> # Set height/width scope.widgetWidth = Math.floor(scope.widgetWidth) if _.isNumber(scope.widgetWidth) scope.widgetHeight = Math.floor(scope.widgetHeight) if _.isNumber(scope.widgetHeight) - $element.width(scope.widgetWidth) - $element.height(scope.widgetHeight) + $element.width scope.widgetWidth + $element.height scope.widgetHeight + $element.css 'display', 'block' # Set gutter padding (other sides are handled by masonry) - $element.css('margin-bottom', layout.gutter) + $element.css 'margin-bottom', layout.gutter # Trigger the post-layout update scope.postLayout() diff --git a/cyclotron-site/app/scripts/dashboards/directives/directives.widgetBody.coffee b/cyclotron-site/app/scripts/dashboards/directives/directives.widgetBody.coffee index 22db8f5..d3ba1c4 100644 --- a/cyclotron-site/app/scripts/dashboards/directives/directives.widgetBody.coffee +++ b/cyclotron-site/app/scripts/dashboards/directives/directives.widgetBody.coffee @@ -28,8 +28,8 @@ cyclotronDirectives.directive 'widgetBody', ($timeout) -> widgetBodyHeight = $widget.outerHeight() - $title.outerHeight() - $footer.outerHeight() $widgetBody.height Math.floor(widgetBodyHeight) - if scope.layout? - scope.layout.widget.widgetBodyHeight = widgetBodyHeight + if scope.widgetLayout? + scope.widgetLayout.widgetBodyHeight = widgetBodyHeight # Update on window resizing $widget.add('.title, .widget-footer').on 'resize', _.throttle(-> diff --git a/cyclotron-site/app/scripts/dashboards/directives/directives.widgetError.coffee b/cyclotron-site/app/scripts/dashboards/directives/directives.widgetError.coffee index 93f1f2e..f117629 100644 --- a/cyclotron-site/app/scripts/dashboards/directives/directives.widgetError.coffee +++ b/cyclotron-site/app/scripts/dashboards/directives/directives.widgetError.coffee @@ -46,12 +46,21 @@ cyclotronDirectives.directive 'widgetError', ($timeout) -> if scope.widget.showWidgetErrors errorMessageLength = $widgetError.width() * widgetBodyHeight / 512 + if _.isObject(scope.dataSourceErrorMessage) + if scope.dataSourceErrorMessage.message? + scope.errorMessage = scope.dataSourceErrorMessage.message + else + scope.errorMessage = scope.dataSourceErrorMessage + + if not _.isString(scope.errorMessage) + $scope.errorMessage = JSON.stringify scope.errorMessage + if errorMessageLength < 30 scope.shortErrorMessage = null - else if scope.dataSourceErrorMessage.length < errorMessageLength - scope.shortErrorMessage = scope.dataSourceErrorMessage + else if scope.errorMessage.length < errorMessageLength + scope.shortErrorMessage = scope.errorMessage else - scope.shortErrorMessage = scope.dataSourceErrorMessage.substring(0, errorMessageLength - 3) + '...' + scope.shortErrorMessage = scope.errorMessage.substring(0, errorMessageLength - 3) + '...' # Vertical align topPadding = (widgetBodyHeight - $errorContainer.height()) / 3 diff --git a/cyclotron-site/app/scripts/dashboards/services/services.dataService.coffee b/cyclotron-site/app/scripts/dashboards/services/services.dataService.coffee index 5952dae..b7869f4 100644 --- a/cyclotron-site/app/scripts/dashboards/services/services.dataService.coffee +++ b/cyclotron-site/app/scripts/dashboards/services/services.dataService.coffee @@ -92,8 +92,9 @@ cyclotronServices.factory 'dataService', ($injector, configService) -> # Create if not in the cache if not Cyclotron.dataSources[name]? - # Get instance - dataSource = $injector.get(type + "DataSource") + + # Get instance by name + dataSource = $injector.get(type + 'DataSource') # Get default options dataSourceProperties = configService?.dashboard.properties.dataSources.options[type]?.properties diff --git a/cyclotron-site/app/scripts/dashboards/services/services.parameterService.coffee b/cyclotron-site/app/scripts/dashboards/services/services.parameterService.coffee index 56b8772..dfe1083 100644 --- a/cyclotron-site/app/scripts/dashboards/services/services.parameterService.coffee +++ b/cyclotron-site/app/scripts/dashboards/services/services.parameterService.coffee @@ -78,7 +78,7 @@ cyclotronServices.factory 'parameterService', ($localForage, $q, $window, config savePersistentParameters: (parameters, dashboard) -> - logService.debug 'savePersistentParameters()' + logService.debug 'Saving persistent parameters to local browser storage' persistentParams = _.filter dashboard.parameters, { persistent: true } _.each persistentParams, (parameterDefinition) -> diff --git a/cyclotron-site/app/scripts/mgmt/controller.help.coffee b/cyclotron-site/app/scripts/mgmt/controller.help.coffee index fe08459..2dc5258 100644 --- a/cyclotron-site/app/scripts/mgmt/controller.help.coffee +++ b/cyclotron-site/app/scripts/mgmt/controller.help.coffee @@ -28,7 +28,10 @@ cyclotronApp.controller 'HelpController', ($scope, $location, configService) -> $location.search 'q', item.name $scope.feelingLucky = -> - $scope.$broadcast('feelingLucky') + $scope.$broadcast 'feelingLucky' + + $scope.findItem = (name) -> + $scope.$broadcast 'findItem', { name: name } # Initialization q = $location.search().q diff --git a/cyclotron-site/app/scripts/mgmt/directives/directives.collapseMenu.coffee b/cyclotron-site/app/scripts/mgmt/directives/directives.collapseMenu.coffee index 546573f..7fb2b0d 100644 --- a/cyclotron-site/app/scripts/mgmt/directives/directives.collapseMenu.coffee +++ b/cyclotron-site/app/scripts/mgmt/directives/directives.collapseMenu.coffee @@ -46,6 +46,18 @@ cyclotronDirectives.directive 'collapseMenu', (filterFilter) -> section.expanded = true $scope.selectItem {'item': child} + # Find and select an item by name + $scope.findItem = (name) -> + _.each $scope.items, (section) -> + if section.name == name + $scope.selectSection section + return false + + child = _.find section.children, { name: name } + if child? + $scope.selectChild child, section + return false + $scope.$watch 'filter', (filter) -> $scope.isFiltered = not _.isEmpty filter @@ -67,18 +79,13 @@ cyclotronDirectives.directive 'collapseMenu', (filterFilter) -> matchingChildren = filterFilter(firstSection.children, $scope.filter) if matchingChildren?.length > 0 $scope.selectChild _.first(matchingChildren), firstSection - + + $scope.$on 'findItem', (event, args) -> + $scope.findItem(args.name) + # Initialize if $scope.initialSelection? - _.each $scope.items, (section) -> - if section.name == $scope.initialSelection - $scope.selectSection section - return false - - child = _.find section.children, { name: $scope.initialSelection } - if child? - $scope.selectChild child, section - return false + $scope.findItem $scope.initialSelection else $scope.selectSection _.first $scope.items diff --git a/cyclotron-site/app/widgets/clock/clock.jade b/cyclotron-site/app/widgets/clock/clock.jade index 4243f05..61349d1 100644 --- a/cyclotron-site/app/widgets/clock/clock.jade +++ b/cyclotron-site/app/widgets/clock/clock.jade @@ -1,3 +1,3 @@ div.clock-widget(ng-controller='ClockWidget') - .the-number(single-number='true', orientation='"vertical"', class='"orientation-vertical"') + .the-number(number-count='1', orientation='"vertical"', class='"orientation-vertical"') h1.big {{ currentTime }} diff --git a/cyclotron-site/app/widgets/table/tableWidget.coffee b/cyclotron-site/app/widgets/table/tableWidget.coffee index c749467..9c8e802 100644 --- a/cyclotron-site/app/widgets/table/tableWidget.coffee +++ b/cyclotron-site/app/widgets/table/tableWidget.coffee @@ -409,7 +409,7 @@ cyclotronApp.controller 'TableWidget', ($scope, $location, dashboardService, dat # Initialize the Data Source $scope.dataSource.init dsDefinition - $scope.$watch 'layout.widget.widgetBodyHeight', (height) -> + $scope.$watch 'widgetLayout.widgetBodyHeight', (height) -> if $scope.widget.pagination?.autoItemsPerPage == true $scope.calculateItemsPerPage(height) , true