diff --git a/CHANGELOG.md b/CHANGELOG.md index df0d862..1f454b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,21 +1,41 @@ +# 1.41.0 (10/27/2016) + +## Features + + - Analytics: Add JavaScript API for Dashboards to record custom events to Cyclotron's analytics backend + + - JavaScript API: Added Cyclotron.currentUser property to access the currently-logged in user (if any) + + - Data Sources: If a Post-Processor doesn't return an array, an error will be displayed in the console. + +## Bug Fixes + + - Clock Widget: Fix issue with tiny text + # 1.40.0 (10/12/2016) ## Features - - Analytics: collect new analytics events for: Login, Logout, Create Dashboard, Modify Dashboard, Push Dashboard + - Analytics: Collect new analytics events for: Login, Logout, Create Dashboard, Modify Dashboard, Push Dashboard - - Dashboard Sidebar: Increased width of sidebar; expanded the first section in the sidebar initially. + - Dashboard Sidebar: Increased width of sidebar; expanded the first section in the sidebar initially - Dashboard Editor: Drag-and-drop to reorder Data Sources, Pages, Widgets, etc. - Dashboard Editor: Added spinner when saving a Dashboard; prevent accidentally double-saving - + # 1.39.0 (09/28/2016) ## Features + - CloudWatch Data Source: Added new Data Source for retrieving data from Amazon CloudWatch + + - JSON Data Source: Added options for AWS signing, allowing use with AWS APIs that require Signature Version 4 + - SSL/TLS: Proxy server initializes itself with a list of trusted root CAs. Added server option for manually providing CAs to trust when executing HTTPS requests + - Highcharts upgraded to 4.2.7 + ## Bug Fixes - Parameters: Serialize Parameters with a Moment.js moment value into the URL using ISO 8601 format @@ -35,7 +55,6 @@ ## Breaking Changes - Removed custom HTTP/HTTPS pool with maxSockets: infinity. This is now the default value in Node.js v0.12.0 and above, so only older versions of Node.js will be affected. As a workaround for older versions of Node.js, set http(s).globalAgent.maxSockets = infinity. - # 1.38.0 (09/02/2016) ## Features diff --git a/cyclotron-site/app/partials/editor/propertySet.jade b/cyclotron-site/app/partials/editor/propertySet.jade index 3e7a0ec..4c8d042 100644 --- a/cyclotron-site/app/partials/editor/propertySet.jade +++ b/cyclotron-site/app/partials/editor/propertySet.jade @@ -58,7 +58,7 @@ editor-view-string-array(model='model[value.name]', label='{{ value.label }}', definition='value', ng-switch-when='string[]') select.form-control(ng-model='model[value.name]', ng-switch-default, title='{{ value.description }}' - ng-options='optionValue.value as optionKey for (optionKey, optionValue) in getOptions(value.name, value.options)') + ng-options='optionValue.value as (optionValue.label || optionKey) for (optionKey, optionValue) in getOptions(value.name, value.options)') option(value='') div(ng-hide='hiddenProperties.length == 0') diff --git a/cyclotron-site/app/partials/help/javascriptApi.jade b/cyclotron-site/app/partials/help/javascriptApi.jade index 70586c6..6670cb9 100644 --- a/cyclotron-site/app/partials/help/javascriptApi.jade +++ b/cyclotron-site/app/partials/help/javascriptApi.jade @@ -28,6 +28,9 @@ table tr td Cyclotron.pageName td Property that returns the name of the currently-displayed Page + tr + td Cyclotron.currentUser + td Property containing an object of information about the logged-in user. If authentication is not enabled, or if the user is not logged in, it will return null. tr td Cyclotron.goToPage(pageNumber) td Navigates to a specific page in the Dashboard (starting with page 1) @@ -51,6 +54,9 @@ table td Downloads the provided data in one of the following formats: 'json', 'csv', 'xlsx'. CSV and XLSX are both tabular formats and may not be correctly formatted with nested data. See also em Cyclotron.currentPage.widgets['widgetName'].exportData(format) | . + tr + td Cyclotron.functions.recordEvent(eventData) + td Records a custom Dashboard event to Cyclotron's analytics database (if enabled). An object of custom key/value pairs can be provided, which are attached to the event. This function can be used to implement custom click tracking, error logging, etc. h4 Built-In Parameters diff --git a/cyclotron-site/app/scripts/common/services/services.analytics.coffee b/cyclotron-site/app/scripts/common/services/services.analytics.coffee index fa2259b..4ce560b 100644 --- a/cyclotron-site/app/scripts/common/services/services.analytics.coffee +++ b/cyclotron-site/app/scripts/common/services/services.analytics.coffee @@ -192,6 +192,11 @@ cyclotronServices.factory 'analyticsService', ($http, $q, $localForage, $locatio visitId: exports.visitId details: details + if exports.currentDashboard? + req.dashboard = + _id: exports.currentDashboard._id + name: exports.currentDashboard.name + uidLoaded.promise.then -> if (userService.authEnabled && userService.isLoggedIn()) req.user = diff --git a/cyclotron-site/app/scripts/common/services/services.commonConfigService.coffee b/cyclotron-site/app/scripts/common/services/services.commonConfigService.coffee index bbc9908..d9b2954 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.40.0' + version: '1.41.0' logging: enableDebug: false @@ -80,22 +80,51 @@ cyclotronServices.factory 'commonConfigService', -> default: 'dark' required: false options: + charcoal: + label: 'Charcoal' + value: 'charcoal' + dashboardBackgroundColor: '#1E2328' + dark: + label: 'Dark' + value: 'dark' + dashboardBackgroundColor: '#2f2f2f' + darkmetro: + label: 'Dark Metro' + value: 'darkmetro' + dashboardBackgroundColor: '#2f2f2f' + gto: + label: 'GTO' + value: 'gto' + dashboardBackgroundColor: 'white' light: + label: 'Light' value: 'light' dashboardBackgroundColor: 'white' lightborderless: + label: 'Light (borderless)' value: 'lightborderless' dashboardBackgroundColor: 'white' - gto: - value: 'gto' - dashboardBackgroundColor: 'white' - dark: - value: 'dark' - dashboardBackgroundColor: '#2f2f2f' dark2: + label: 'Very Dark' value: 'dark2' dashboardBackgroundColor: 'black' order: 5 + + themeVariant: + label: 'Theme Variant' + description: 'The default Theme Variant for the Dashboard; each Theme may or may not implement each variant. If this property is set, the value will be applies to any Pages that have not specified a Theme Variant. If it is not set, the default variant will be used.' + type: 'string' + default: 'default' + required: false + defaultHidden: true + options: + default: + value: 'default' + transparent: + value: 'transparent' + 'transparent-unpadded': + value: 'transparent-unpadded' + order: 6 style: label: 'Style' @@ -109,7 +138,7 @@ cyclotronServices.factory 'commonConfigService', -> fullscreen: value: 'fullscreen' defaultHidden: true - order: 6 + order: 7 autoRotate: label: 'Auto-Rotate' @@ -408,6 +437,14 @@ cyclotronServices.factory 'commonConfigService', -> required: false defaultHidden: true order: 110 + themeVariant: + label: 'Theme Variant' + description: 'If set, overrides the Page theme variant and allows a widget to have a different theme variant from the rest of the Page and Widgets.' + type: 'string' + inherit: true + required: false + defaultHidden: true + order: 111 noData: label: 'No Data Message' description: 'If set, displays this message in the Widget when no data is loaded from the Data Source. If not set, no message will be displayed' @@ -415,7 +452,7 @@ cyclotronServices.factory 'commonConfigService', -> inlineJs: true required: false defaultHidden: true - order: 111 + order: 120 noscroll: label: 'No Scroll' description: 'If set to true, the widget will not have scrollbars and any overflow will be hidden. The effect of this setting varies per widget.' @@ -423,7 +460,7 @@ cyclotronServices.factory 'commonConfigService', -> default: false required: false defaultHidden: true - order: 112 + order: 121 allowFullscreen: label: 'Allow Fullscreen' description: 'If true, the Widget can be maximized to fill the entire Dashboard; if false, the ability to view in fullscreen is disabled. This property overrides the Page setting.' @@ -431,7 +468,7 @@ cyclotronServices.factory 'commonConfigService', -> inherit: true required: false defaultHidden: true - order: 113 + order: 122 allowExport: label: 'Allow Export' description: 'If true, the Widget data can be exported via a dropdown menu in the Widget. This property overrides the Page setting.' @@ -439,7 +476,7 @@ cyclotronServices.factory 'commonConfigService', -> inherit: true required: false defaultHidden: true - order: 114 + order: 123 showWidgetErrors: label: 'Show Error Messages on Widgets' description: 'If true, allows error messages to be displayed on Widgets. This property overrides the Page setting.' @@ -447,7 +484,7 @@ cyclotronServices.factory 'commonConfigService', -> required: false inherit: true defaultHidden: true - order: 115 + order: 124 hidden: label: 'Hidden' description: 'If true, the Widget will not be displayed in the Dashboard and will not occupy space in the Layout rendering. The Widget will still be initialized, however.' @@ -455,7 +492,7 @@ cyclotronServices.factory 'commonConfigService', -> default: false required: false defaultHidden: true - order: 116 + order: 125 order: 3 duration: label: 'Auto-Rotate Duration (seconds)' @@ -482,6 +519,14 @@ cyclotronServices.factory 'commonConfigService', -> required: false defaultHidden: true order: 6 + themeVariant: + label: 'Theme Variant' + description: 'The theme variant for the Page. If not set, the Dashboard setting or default value will apply.' + type: 'string' + inherit: true + required: false + defaultHidden: true + order: 7 style: label: 'Style' description: 'The style for the Page. If not set, the Dashboard setting or default value will apply.' @@ -489,7 +534,7 @@ cyclotronServices.factory 'commonConfigService', -> inherit: true required: false defaultHidden: true - order: 7 + order: 8 allowFullscreen: label: 'Allow Fullscreen' description: 'If true, each Widget on the page can be maximized to fill the entire Dashboard. This setting can be overridden by each Widget.' @@ -497,7 +542,7 @@ cyclotronServices.factory 'commonConfigService', -> inherit: true required: false defaultHidden: true - order: 8 + order: 10 allowExport: label: 'Allow Export' description: 'If true, the Widget data can be exported via a dropdown menu in the Widget. This setting can be overridden by each Widget.' @@ -505,7 +550,7 @@ cyclotronServices.factory 'commonConfigService', -> inherit: true required: false defaultHidden: true - order: 9 + order: 11 showWidgetErrors: label: 'Show Error Messages on Widgets' description: 'If true, allows error messages to be displayed on Widgets. This setting can be overridden by each Widget.' @@ -513,7 +558,7 @@ cyclotronServices.factory 'commonConfigService', -> required: false inherit: true defaultHidden: true - order: 10; + order: 12; dataSources: label: 'Data Sources' @@ -1858,6 +1903,9 @@ cyclotronServices.factory 'commonConfigService', -> dark: options: dbackgroundColor: '#222222' + darkmetro: + options: + dbackgroundColor: '#202020' chart: name: 'chart' @@ -2464,6 +2512,436 @@ cyclotronServices.factory 'commonConfigService', -> [1, '#333'] ] trackBorderColor: '#666' + + darkmetro: + colors: [ + '#007D9D' #Blue + '#82B93A' #Green + '#E3AAD5' #Pink + '#EBDC46' #Yellow + '#AC5B41' #Red + '#D1D1D0' #Offwhite + '#B07288' #Purple + ] + chart: + backgroundColor: null #'#333333' + borderWidth: 0 + borderRadius: 0 + plotBackgroundColor: null + plotShadow: false + plotBorderWidth: 0 + style: + fontFamily: '"Open Sans", sans-serif' + color: '#FFF' + drilldown: + activeAxisLabelStyle: + color: '#999' + textDecoration: 'none' + activeDataLabelStyle: + color: '#999' + textDecoration: 'none' + title: + style: + color: '#FFF' + font: '16px "Lato", sans-serif' + fontWeight: 'bold' + subtitle: + style: + color: '#FFF' + font: '12px "Lato", sans-serif' + xAxis: + gridLineWidth: 0 + lineColor: '#999' + tickColor: '#999' + labels: + style: + color: '#999' + fontSize: '11px' + title: + style: + color: '#EEE' + fontSize: '14px' + fontWeight: '300' + yAxis: + alternateGridColor: null + minorTickInterval: null + gridLineColor: 'rgba(255, 255, 255, .1)' + minorGridLineColor: 'rgba(255,255,255,0.07)' + lineWidth: 0 + tickWidth: 0 + labels: + style: + color: '#999' + fontSize: '11px' + title: + style: + color: '#EEE' + fontSize: '14px' + fontWeight: '300' + legend: + borderRadius: 0 + borderWidth: 0 + itemStyle: + color: '#CCC' + itemHoverStyle: + color: '#FFF' + itemHiddenStyle: + color: '#333' + symbolWidth: 40 + labels: + style: + color: '#CCC' + tooltip: + backgroundColor: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0, 'rgba(96, 96, 96, .8)'] + [1, 'rgba(16, 16, 16, .8)'] + ] + borderWidth: 0 + style: + color: '#FFF' + plotOptions: + series: + dataLabels: + style: + color: '#999' + textShadow: false + shadow: true + marker: + enabled: false + states: + hover: + enabled: true + bar: + borderWidth: 0 + column: + borderWidth: 0 + line: + dataLabels: + color: '#CCC' + marker: + lineColor: '#333' + pie: + borderWidth: 0 + dataLabels: + color: '#999' + fontSize: '14px' + spline: + marker: + lineColor: '#333' + scatter: + marker: + lineColor: '#333' + candlestick: + lineColor: 'white' + + toolbar: + itemStyle: + color: '#CCC' + + navigation: + buttonOptions: + symbolStroke: '#DDDDDD' + hoverSymbolStroke: '#FFFFFF' + theme: + fill: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.4, '#606060'] + [0.6, '#333333'] + ] + stroke: '#000000' + + # scroll charts + rangeSelector: + buttonTheme: + fill: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.4, '#888'] + [0.6, '#555'] + ] + stroke: '#000000' + style: + color: '#CCC' + fontWeight: 'bold' + states: + hover: + fill: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.4, '#BBB'] + [0.6, '#888'] + ] + stroke: '#000000' + style: + color: 'white' + select: + fill: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.1, '#000'] + [0.3, '#333'] + ] + stroke: '#000000' + style: + color: 'yellow' + inputStyle: + backgroundColor: '#333' + color: 'silver' + labelStyle: + color: 'silver' + + navigator: + handles: + backgroundColor: '#666' + borderColor: '#AAA' + outlineColor: '#CCC' + maskFill: 'rgba(16, 16, 16, 0.5)' + series: + color: '#7798BF' + lineColor: '#A6C7ED' + + scrollbar: + barBackgroundColor: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.4, '#888'] + [0.6, '#555'] + ] + barBorderColor: '#CCC' + buttonArrowColor: '#CCC' + buttonBackgroundColor: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.4, '#888'] + [0.6, '#555'] + ] + buttonBorderColor: '#CCC' + rifleColor: '#FFF' + trackBackgroundColor: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0, '#000'] + [1, '#333'] + ] + trackBorderColor: '#666' + + charcoal: + colors: [ + '#007D9D' #Blue + '#82B93A' #Green + '#E3AAD5' #Pink + '#EBDC46' #Yellow + '#AC5B41' #Red + '#D1D1D0' #Offwhite + '#B07288' #Purple + ] + chart: + backgroundColor: null #'#333333' + borderWidth: 0 + borderRadius: 0 + plotBackgroundColor: null + plotShadow: false + plotBorderWidth: 0 + style: + fontFamily: '"Open Sans", sans-serif' + color: '#FFF' + drilldown: + activeAxisLabelStyle: + color: '#999' + textDecoration: 'none' + activeDataLabelStyle: + color: '#999' + textDecoration: 'none' + title: + style: + color: '#FFF' + font: '16px "Lato", sans-serif' + fontWeight: 'bold' + subtitle: + style: + color: '#FFF' + font: '12px "Lato", sans-serif' + xAxis: + gridLineWidth: 0 + lineColor: '#999' + tickColor: '#999' + labels: + style: + color: '#999' + fontSize: '11px' + title: + style: + color: '#EEE' + fontSize: '14px' + fontWeight: '300' + yAxis: + alternateGridColor: null + minorTickInterval: null + gridLineColor: 'rgba(255, 255, 255, .1)' + minorGridLineColor: 'rgba(255,255,255,0.07)' + lineWidth: 0 + tickWidth: 0 + labels: + style: + color: '#999' + fontSize: '11px' + title: + style: + color: '#EEE' + fontSize: '14px' + fontWeight: '300' + legend: + borderRadius: 0 + borderWidth: 0 + itemStyle: + color: '#CCC' + itemHoverStyle: + color: '#FFF' + itemHiddenStyle: + color: '#333' + symbolWidth: 40 + labels: + style: + color: '#CCC' + tooltip: + backgroundColor: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0, 'rgba(96, 96, 96, .8)'] + [1, 'rgba(16, 16, 16, .8)'] + ] + borderWidth: 0 + style: + color: '#FFF' + plotOptions: + series: + dataLabels: + style: + color: '#999' + textShadow: false + shadow: false + marker: + enabled: false + states: + hover: + enabled: true + bar: + borderWidth: 0 + column: + borderWidth: 0 + line: + dataLabels: + color: '#CCC' + marker: + lineColor: '#333' + pie: + borderWidth: 0 + dataLabels: + color: '#999' + fontSize: '14px' + spline: + marker: + lineColor: '#333' + scatter: + marker: + lineColor: '#333' + candlestick: + lineColor: 'white' + + toolbar: + itemStyle: + color: '#CCC' + + navigation: + buttonOptions: + symbolStroke: '#DDDDDD' + hoverSymbolStroke: '#FFFFFF' + theme: + fill: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.4, '#606060'] + [0.6, '#333333'] + ] + stroke: '#000000' + + # scroll charts + rangeSelector: + buttonTheme: + fill: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.4, '#888'] + [0.6, '#555'] + ] + stroke: '#000000' + style: + color: '#CCC' + fontWeight: 'bold' + states: + hover: + fill: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.4, '#BBB'] + [0.6, '#888'] + ] + stroke: '#000000' + style: + color: 'white' + select: + fill: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.1, '#000'] + [0.3, '#333'] + ] + stroke: '#000000' + style: + color: 'yellow' + inputStyle: + backgroundColor: '#333' + color: 'silver' + labelStyle: + color: 'silver' + + navigator: + handles: + backgroundColor: '#666' + borderColor: '#AAA' + outlineColor: '#CCC' + maskFill: 'rgba(16, 16, 16, 0.5)' + series: + color: '#7798BF' + lineColor: '#A6C7ED' + + scrollbar: + barBackgroundColor: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.4, '#888'] + [0.6, '#555'] + ] + barBorderColor: '#CCC' + buttonArrowColor: '#CCC' + buttonBackgroundColor: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0.4, '#888'] + [0.6, '#555'] + ] + buttonBorderColor: '#CCC' + rifleColor: '#FFF' + trackBackgroundColor: + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 } + stops: [ + [0, '#000'] + [1, '#333'] + ] + trackBorderColor: '#666' clock: name: 'clock' @@ -2593,6 +3071,7 @@ cyclotronServices.factory 'commonConfigService', -> required: false inlineJs: true order: 30 + html: name: 'html' icon: 'fa-html5' @@ -3582,6 +4061,9 @@ cyclotronServices.factory 'commonConfigService', -> exports.dashboard.properties.pages.properties.theme.options = exports.dashboard.properties.theme.options exports.dashboard.properties.pages.properties.widgets.properties.theme.options = exports.dashboard.properties.theme.options + exports.dashboard.properties.pages.properties.themeVariant.options = exports.dashboard.properties.themeVariant.options + exports.dashboard.properties.pages.properties.widgets.properties.themeVariant.options = exports.dashboard.properties.themeVariant.options + # Copy Style options to inherited locations exports.dashboard.properties.pages.properties.style.options = exports.dashboard.properties.style.options diff --git a/cyclotron-site/app/scripts/common/services/services.logService.coffee b/cyclotron-site/app/scripts/common/services/services.logService.coffee index b3e1d86..78b3874 100644 --- a/cyclotron-site/app/scripts/common/services/services.logService.coffee +++ b/cyclotron-site/app/scripts/common/services/services.logService.coffee @@ -28,6 +28,9 @@ cyclotronServices.factory 'logService', ($window, configService) -> writeLog = (args) -> $window.console.log '[' + now() + '] ' + _.map(args, getString).join ' ' + writeError = (args) -> + $window.console.error '[' + now() + '] ' + _.map(args, getString).join ' ' + service = { debug: -> args = Array.prototype.slice.call arguments @@ -42,7 +45,7 @@ cyclotronServices.factory 'logService', ($window, configService) -> error: -> args = Array.prototype.slice.call arguments args.unshift 'ERROR:' - writeLog args + writeError args } if configService.logging?.enableDebug == false diff --git a/cyclotron-site/app/scripts/common/services/services.userService.coffee b/cyclotron-site/app/scripts/common/services/services.userService.coffee index 9871ecd..c04f304 100644 --- a/cyclotron-site/app/scripts/common/services/services.userService.coffee +++ b/cyclotron-site/app/scripts/common/services/services.userService.coffee @@ -14,7 +14,7 @@ # language governing permissions and limitations under the License. ### -cyclotronServices.factory 'userService', ($http, $localForage, $q, $rootScope, configService, logService) -> +cyclotronServices.factory 'userService', ($http, $localForage, $q, $rootScope, $window, configService, logService) -> loggedIn = false currentSession = null @@ -95,6 +95,8 @@ cyclotronServices.factory 'userService', ($http, $localForage, $q, $rootScope, c loggedIn = true $rootScope.$broadcast 'login', { } + if $window.Cyclotron? + $window.Cyclotron.currentUser = session.user alertify.success('Logged in as ' + session.user.name + '', 2500) deferred.resolve(session) @@ -148,6 +150,8 @@ cyclotronServices.factory 'userService', ($http, $localForage, $q, $rootScope, c $localForage.removeItem('session') $rootScope.$broadcast('logout') + if $window.Cyclotron? + $window.Cyclotron.currentUser = null alertify.log('Logged Out', 2500) deferred.resolve() diff --git a/cyclotron-site/app/scripts/dashboards/controller.dashboard.coffee b/cyclotron-site/app/scripts/dashboards/controller.dashboard.coffee index 976c5cd..7f58cad 100644 --- a/cyclotron-site/app/scripts/dashboards/controller.dashboard.coffee +++ b/cyclotron-site/app/scripts/dashboards/controller.dashboard.coffee @@ -45,13 +45,19 @@ cyclotronApp.controller 'DashboardController', ($scope, $stateParams, $localFora # Load URL querystring into Cyclotron.parameters $window.Cyclotron = version: configService.version + currentUser: userService.currentUser() dataSources: {} functions: forceUpdate: -> $scope.$apply() + exportData: (format, data, name = $scope.originalDashboardName) -> return unless data? downloadService.download name, format, data + recordEvent: (eventData) -> + analyticsService.recordEvent 'custom', eventData + + parameters: _.clone $location.search() data: cyclotronDataService diff --git a/cyclotron-site/app/scripts/dashboards/dataSources/dataSources.factory.coffee b/cyclotron-site/app/scripts/dashboards/dataSources/dataSources.factory.coffee index 890c325..056937a 100644 --- a/cyclotron-site/app/scripts/dashboards/dataSources/dataSources.factory.coffee +++ b/cyclotron-site/app/scripts/dashboards/dataSources/dataSources.factory.coffee @@ -168,6 +168,8 @@ cyclotronDataSources.factory 'dataSourceFactory', ($rootScope, $interval, config # or return a new array that replaces it if _.isArray postProcessedResult cachedResult[resultSetName].data = postProcessedResult + else + logService.error 'The Post-Processor for "' + currentOptions.name + '" did not return an array; ignoring and using original result.' return diff --git a/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardPage.coffee b/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardPage.coffee index 8908a9c..6f42a8d 100644 --- a/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardPage.coffee +++ b/cyclotron-site/app/scripts/dashboards/directives/directives.dashboardPage.coffee @@ -37,7 +37,7 @@ cyclotronDirectives.directive 'dashboardPage', ($compile, $window, $timeout, con template: '
' + '
' + - '
' + '
' diff --git a/cyclotron-site/app/scripts/dashboards/directives/directives.widgetBody.coffee b/cyclotron-site/app/scripts/dashboards/directives/directives.widgetBody.coffee index 80d2559..8d0d3b7 100644 --- a/cyclotron-site/app/scripts/dashboards/directives/directives.widgetBody.coffee +++ b/cyclotron-site/app/scripts/dashboards/directives/directives.widgetBody.coffee @@ -26,6 +26,7 @@ cyclotronDirectives.directive 'widgetBody', ($timeout) -> $title = $widget.find '.title' $footer = $widget.find '.widget-footer' widgetBodyHeight = $widget.outerHeight() - $title.outerHeight() - $footer.outerHeight() + widgetBodyHeight -= parseInt($widgetBody.css('marginTop')) + parseInt($widgetBody.css('marginBottom')) $widgetBody.height Math.floor(widgetBodyHeight) if scope.widgetLayout? diff --git a/cyclotron-site/app/scripts/mgmt/controller.guiEditor.coffee b/cyclotron-site/app/scripts/mgmt/controller.guiEditor.coffee index eb31472..118d3e6 100644 --- a/cyclotron-site/app/scripts/mgmt/controller.guiEditor.coffee +++ b/cyclotron-site/app/scripts/mgmt/controller.guiEditor.coffee @@ -352,6 +352,8 @@ cyclotronApp.controller 'GuiEditorController', ($scope, $state, $stateParams, $l $state.go('edit.details', { dashboardName: dashboardName}) $scope.editor.isNew = false $scope.editor.hasEditPermission = userService.hasEditPermission $scope.editor.dashboardWrapper + .catch (e) -> + $scope.isSaving = false else dashboardToSave = _.cloneDeep $scope.editor.dashboardWrapper @@ -371,6 +373,8 @@ cyclotronApp.controller 'GuiEditorController', ($scope, $state, $stateParams, $l $scope.editor.isDirty = false $scope.isSaving = false $location.search('rev', null) + .catch (e) -> + $scope.isSaving = false catch e $scope.isSaving = false diff --git a/cyclotron-site/app/styles/_widgets.less b/cyclotron-site/app/styles/_widgets.less new file mode 100644 index 0000000..afb9ec2 --- /dev/null +++ b/cyclotron-site/app/styles/_widgets.less @@ -0,0 +1,16 @@ +/* Import all Widget styles */ +@import "../widgets/annotationChart/_annotationChart.less"; +@import "../widgets/chart/_chart.less"; +@import "../widgets/clock/_clock.less"; +@import "../widgets/header/_header.less"; +@import "../widgets/html/_html.less"; +@import "../widgets/iframe/_iframe.less"; +@import "../widgets/image/_image.less"; +@import "../widgets/javascript/_javascript.less"; +@import "../widgets/number/_number.less"; +@import "../widgets/qrcode/_qrcode.less"; +@import "../widgets/stoplight/_stoplight.less"; +@import "../widgets/table/_table.less"; +@import "../widgets/tableau/_tableau.less"; +@import "../widgets/treemap/_treemap.less"; +@import "../widgets/youtube/_youtube.less"; diff --git a/cyclotron-site/app/styles/dashboards/dashboard.less b/cyclotron-site/app/styles/dashboards/dashboard.less index aa7b729..9f4c5b9 100644 --- a/cyclotron-site/app/styles/dashboards/dashboard.less +++ b/cyclotron-site/app/styles/dashboards/dashboard.less @@ -202,7 +202,6 @@ @media only screen and (max-width: 1024px) { font-size: 1.5em; } @media only screen and (max-width: 600px) { font-size: 1.3em; } font-size: 1.8em; - margin: 0; &.big { font-size: 3.3em; diff --git a/cyclotron-site/app/styles/themes/charcoal.less b/cyclotron-site/app/styles/themes/charcoal.less new file mode 100644 index 0000000..4e96d84 --- /dev/null +++ b/cyclotron-site/app/styles/themes/charcoal.less @@ -0,0 +1,187 @@ +/* + * Copyright (c) 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. + * You may obtain a copy of the License at + * + * http://www.opensource.org/licenses/mit-license.php + * + * 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. + */ + +/* Theme: charcoal */ + +@import "../../../vendor/lesselements/_elements.less"; +@import "../common/variables.less"; + +/* Variables */ +@color: #efefef; +@pageBackgroundColor: #152029; +@widgetBackgroundColor: #3d454c; +@widgetBackgroundAccentColor: darken(#565F67, 5%); +@widgetBackgroundAccentBorderColor: lighten(@widgetBackgroundAccentColor, 10%); + +@linkColor: lighten(@color, 15%); +@headerColor: #353B41; +@tableRowHoverBackgroundColor: lighten(@widgetBackgroundColor, 20%); +@tableBorderColor: #ccc; +@tableHeaderBorderBottom: 0; + +@fontFamily: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; + +/* Dashboard Styles */ +.dashboard.dashboard-charcoal { + background-color: @pageBackgroundColor; + + .dashboard-page-background { + background-color: @pageBackgroundColor; + } + + @sidebar-outline-color: #666; + @sidebar-expander-color: #ddd; + @sidebar-header-color: @color; + @sidebar-header-background-color: lighten(@pageBackgroundColor, 1%); + @sidebar-iconbar-color: lighten(@color, 10%); + @sidebar-iconbar-background-color: @widgetBackgroundColor; //lighten(@pageBackgroundColor, 8%); + @sidebar-heading-color: @color; + @sidebar-heading-background-color: lighten(@pageBackgroundColor, 15%);; + @sidebar-heading-border-bottom: 1px solid @widgetBackgroundColor; + @sidebar-panel-color: @widgetBackgroundColor; + @sidebar-panel-background-color: lighten(@pageBackgroundColor, 70%); + @sidebar-footer-color: @color; + @sidebar-footer-background-color: lighten(@pageBackgroundColor, 1%); + + /* Dashboard elements */ + @import "../dashboards/_sidebar.less"; +} + +.dashboard-page { + /* Well style, normal only */ + &.normal { + .dashboard-charcoal.dashboard-widgetwrapper > .dashboard-widget { + padding: 0px; + } + } + + /* Page styles */ + &.dashboard-charcoal { + color: @color; + background-color: @pageBackgroundColor; + } +} + +/* Widget styles */ +.dashboard-widgetwrapper.dashboard-charcoal { + + color: @color; + + > .tooltip { + .tooltip-inner { + background-color: @pageBackgroundColor; + color: @color; + } + .tooltip-arrow { + border-top-color: @pageBackgroundColor; + border-bottom-color: @pageBackgroundColor; + } + } + + > .dashboard-widget { + + .widget-body { + box-sizing: border-box; + margin: 10px; + } + + font-family: @fontFamily; + + background-color: @widgetBackgroundColor; + + h1,h2,h3,h4,h5,h6 { + color: White; + } + + button, + input, + optgroup, + select, + textarea { + color: black; + } + + a { + color: @linkColor; + text-decoration: none; + border-bottom: 1px dotted #888; + + &:hover { + color: lighten(@color, 30%); + } + } + } + + /* Import widget styles, using the theme variables */ + @import "../_widgets.less"; + + /* Extra styles */ + h1.title { + box-sizing: border-box; + background-color: @widgetBackgroundAccentColor; + font-family: @fontFamily; + + line-height: 3rem; + padding-left: 1rem; + + > .tooltip { + .tooltip-inner { + background-color: @pageBackgroundColor; + color: @color; + } + .tooltip-arrow { + border-top-color: @pageBackgroundColor; + border-bottom-color: @pageBackgroundColor; + } + } + } + + .header-widget { + padding: 10px; + .parameters { + .header-parameter, button { + .rounded(4px); + } + } + } +} + +/* Transparent Variant */ +.dashboard-widgetwrapper.dashboard-charcoal.theme-variant-transparent { + > .dashboard-widget { + background-color: transparent; + color: #ddd; + } +} + +/* Transparent-Unpadded Variant */ +.dashboard-widgetwrapper.dashboard-charcoal.theme-variant-transparent-unpadded { + > .dashboard-widget { + padding: 0 !important; + background-color: transparent; + color: #ddd; + + .widget-body { + margin: 0; + } + } +} + +.dashboard-charcoal.dashboard-controls { + color: @color; + a { color: @color; } + background-color: @pageBackgroundColor; +} diff --git a/cyclotron-site/app/styles/themes/dark.less b/cyclotron-site/app/styles/themes/dark.less index c01ecba..ea9ae3c 100644 --- a/cyclotron-site/app/styles/themes/dark.less +++ b/cyclotron-site/app/styles/themes/dark.less @@ -30,6 +30,7 @@ @headerColor: #202020; @tableRowHoverBackgroundColor: lighten(@widgetBackgroundColor, 20%); @tableBorderColor: #ccc; +@tableHeaderBorderBottom: 1px dashed #999; /* Dashboard Styles */ .dashboard.dashboard-dark { @@ -78,7 +79,8 @@ } /* Widget styles */ -.dashboard-dark.dashboard-widgetwrapper { +.dashboard-widgetwrapper.dashboard-dark { + color: @color; > .tooltip { .tooltip-inner { @@ -92,9 +94,7 @@ } > .dashboard-widget { - - color: @color; - background-color: @widgetBackgroundColor; + background-color: @widgetBackgroundColor; h1,h2,h3,h4,h5,h6 { color: White; @@ -118,33 +118,9 @@ } } } -} - -.dashboard-dark.dashboard-controls { - color: @color; - a { color: @color; } - background-color: @pageBackgroundColor; - border: 1px dotted @color; -} - -.dashboard-dark.dashboard-widgetwrapper { /* Import widget styles, using the theme variables */ - @import "../../widgets/annotationChart/_annotationChart.less"; - @import "../../widgets/chart/_chart.less"; - @import "../../widgets/clock/_clock.less"; - @import "../../widgets/header/_header.less"; - @import "../../widgets/html/_html.less"; - @import "../../widgets/iframe/_iframe.less"; - @import "../../widgets/image/_image.less"; - @import "../../widgets/javascript/_javascript.less"; - @import "../../widgets/number/_number.less"; - @import "../../widgets/qrcode/_qrcode.less"; - @import "../../widgets/stoplight/_stoplight.less"; - @import "../../widgets/table/_table.less"; - @import "../../widgets/tableau/_tableau.less"; - @import "../../widgets/treemap/_treemap.less"; - @import "../../widgets/youtube/_youtube.less"; + @import "../_widgets.less"; /* Extra styles */ h1.title { @@ -170,3 +146,30 @@ } } } + +/* Transparent Variant */ +.dashboard-widgetwrapper.dashboard-dark.theme-variant-transparent { + > .dashboard-widget { + background-color: transparent; + box-shadow: none !important; + color: #ddd; + } +} + +/* Transparent-Unpadded Variant */ +.dashboard-widgetwrapper.dashboard-dark.theme-variant-transparent-unpadded { + > .dashboard-widget { + padding: 0 !important; + background-color: transparent; + box-shadow: none !important; + color: #ddd; + } +} + +.dashboard-dark.dashboard-controls { + color: @color; + a { color: @color; } + background-color: @pageBackgroundColor; + border: 1px dotted @color; +} + diff --git a/cyclotron-site/app/styles/themes/dark2.less b/cyclotron-site/app/styles/themes/dark2.less index 93d077f..2ac73b0 100644 --- a/cyclotron-site/app/styles/themes/dark2.less +++ b/cyclotron-site/app/styles/themes/dark2.less @@ -32,6 +32,7 @@ @tableRowHoverBackgroundColor: @accentColor; @headerPadding: 5px; @tableBorderColor: #ccc; +@tableHeaderBorderBottom: 0; /* Dashboard Styles */ .dashboard.dashboard-dark2 { @@ -74,7 +75,9 @@ } /* Widget styles */ -.dashboard-dark2.dashboard-widgetwrapper { +.dashboard-widgetwrapper.dashboard-dark2 { + color: @color; + > .widget-fullscreen, > .widget-helptext { top: (2*@headerPadding); right: (2*@headerPadding); @@ -96,8 +99,6 @@ } > .dashboard-widget { - - color: @color; background-color: @widgetBackgroundColor; h1,h2,h3,h4,h5,h6 { @@ -128,39 +129,14 @@ } } } -} -.dashboard-dark2.dashboard-controls { - color: @color; - a { color: @color; } - background-color: @pageBackgroundColor; - border: 1px solid @widgetBackgroundColor; -} - - -.dashboard-dark2.dashboard-widgetwrapper { /* Import widget styles, using the theme variables */ - @import "../../widgets/annotationChart/_annotationChart.less"; - @import "../../widgets/chart/_chart.less"; - @import "../../widgets/clock/_clock.less"; - @import "../../widgets/header/_header.less"; - @import "../../widgets/html/_html.less"; - @import "../../widgets/iframe/_iframe.less"; - @import "../../widgets/image/_image.less"; - @import "../../widgets/javascript/_javascript.less"; - @import "../../widgets/number/_number.less"; - @import "../../widgets/qrcode/_qrcode.less"; - @import "../../widgets/stoplight/_stoplight.less"; - @import "../../widgets/table/_table.less"; - @import "../../widgets/tableau/_tableau.less"; - @import "../../widgets/treemap/_treemap.less"; - @import "../../widgets/youtube/_youtube.less"; + @import "../_widgets.less"; /* Extra styles */ .table-widget table { margin-top: 4px; th { - border-bottom: 0px; font-weight: bold; font-size: .9rem; } @@ -175,3 +151,26 @@ } } } + +/* Transparent Variant */ +.dashboard-widgetwrapper.dashboard-dark2.theme-variant-transparent { + > .dashboard-widget { + background-color: transparent; + } +} + +/* Transparent-Unpadded Variant */ +.dashboard-widgetwrapper.dashboard-dark2.theme-variant-transparent-unpadded { + > .dashboard-widget { + padding: 0 !important; + background-color: transparent; + } +} + +.dashboard-dark2.dashboard-controls { + color: @color; + a { color: @color; } + background-color: @pageBackgroundColor; + border: 1px solid @widgetBackgroundColor; +} + diff --git a/cyclotron-site/app/styles/themes/darkmetro.less b/cyclotron-site/app/styles/themes/darkmetro.less new file mode 100644 index 0000000..6bcb532 --- /dev/null +++ b/cyclotron-site/app/styles/themes/darkmetro.less @@ -0,0 +1,166 @@ +/* + * Copyright (c) 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. + * You may obtain a copy of the License at + * + * http://www.opensource.org/licenses/mit-license.php + * + * 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. + */ + +/* Theme: darkmetro */ + +@import "../../../vendor/lesselements/_elements.less"; +@import "../common/variables.less"; + +/* Variables */ +@color: #D1D1D1; +@pageBackgroundColor: #2f2f2f; +@widgetBackgroundColor: #252525; +@widgetBackgroundAccentColor: @pageBackgroundColor; +@widgetBackgroundAccentBorderColor: lighten(@widgetBackgroundAccentColor, 10%); + +@linkColor: lighten(@color, 15%); +@headerColor: #202020; +@tableRowHoverBackgroundColor: lighten(@widgetBackgroundColor, 20%); +@tableBorderColor: #ccc; +@tableHeaderBorderBottom: 1px solid #666; + +/* Dashboard Styles */ +.dashboard.dashboard-darkmetro { + background-color: @pageBackgroundColor; + + .dashboard-page-background { + background-color: @pageBackgroundColor; + } + + @sidebar-outline-color: #666; + @sidebar-expander-color: #ddd; + @sidebar-header-color: @color; + @sidebar-header-background-color: lighten(@pageBackgroundColor, 1%); + @sidebar-iconbar-color: lighten(@color, 10%); + @sidebar-iconbar-background-color: @widgetBackgroundColor; //lighten(@pageBackgroundColor, 8%); + @sidebar-heading-color: @color; + @sidebar-heading-background-color: lighten(@pageBackgroundColor, 15%);; + @sidebar-heading-border-bottom: 1px solid @widgetBackgroundColor; + @sidebar-panel-color: @widgetBackgroundColor; + @sidebar-panel-background-color: lighten(@pageBackgroundColor, 70%); + @sidebar-footer-color: @color; + @sidebar-footer-background-color: lighten(@pageBackgroundColor, 1%); + + /* Dashboard elements */ + @import "../dashboards/_sidebar.less"; +} + +.dashboard-page { + /* Well style, normal only */ + &.normal { + .dashboard-darkmetro.dashboard-widgetwrapper > .dashboard-widget { + padding: 10px; + } + } + + /* Page styles */ + &.dashboard-darkmetro { + color: @color; + background-color: @pageBackgroundColor; + } +} + +/* Widget styles */ +.dashboard-widgetwrapper.dashboard-darkmetro { + color: @color; + + > .tooltip { + .tooltip-inner { + background-color: @pageBackgroundColor; + color: @color; + } + .tooltip-arrow { + border-top-color: @pageBackgroundColor; + border-bottom-color: @pageBackgroundColor; + } + } + + > .dashboard-widget { + background-color: @widgetBackgroundColor; + + h1,h2,h3,h4,h5,h6 { + color: White; + } + + button, + input, + optgroup, + select, + textarea { + color: black; + } + + a { + color: @linkColor; + text-decoration: none; + border-bottom: 1px dotted #888; + + &:hover { + color: lighten(@color, 30%); + } + } + } + + /* Import widget styles, using the theme variables */ + @import "../_widgets.less"; + + /* Extra styles */ + h1.title { + > .tooltip { + .tooltip-inner { + background-color: @pageBackgroundColor; + color: @color; + } + .tooltip-arrow { + border-top-color: @pageBackgroundColor; + border-bottom-color: @pageBackgroundColor; + } + } + } + + .table-widget table th { + font-style: italic; + } + + .header-widget .parameters { + .header-parameter, button { + .rounded(4px); + } + } +} + +/* Transparent Variant */ +.dashboard-widgetwrapper.dashboard-darkmetro.theme-variant-transparent { + > .dashboard-widget { + background-color: transparent; + color: #ddd; + } +} + +/* Transparent-Unpadded Variant */ +.dashboard-widgetwrapper.dashboard-darkmetro.theme-variant-transparent-unpadded { + > .dashboard-widget { + padding: 0 !important; + background-color: transparent; + color: #ddd; + } +} + +.dashboard-darkmetro.dashboard-controls { + color: @color; + a { color: @color; } + background-color: @pageBackgroundColor; +} diff --git a/cyclotron-site/app/styles/themes/gto.less b/cyclotron-site/app/styles/themes/gto.less index a238a9c..824861b 100644 --- a/cyclotron-site/app/styles/themes/gto.less +++ b/cyclotron-site/app/styles/themes/gto.less @@ -25,6 +25,7 @@ @headerColor: #16365c; @tableRowHoverBackgroundColor: #efefef; @tableBorderColor: #555; +@tableHeaderBorderBottom: 1px dashed #999; @pageBackgroundColor: white; @widgetBackgroundColor: white; @@ -60,46 +61,25 @@ } /* Widget styles */ -.dashboard-gto.dashboard-widgetwrapper > .dashboard-widget { - +.dashboard-widgetwrapper.dashboard-gto { color: @color; - background-color: @widgetBackgroundColor; - a { - color: @linkColor; - text-decoration: none; - border-bottom: 1px dotted #888; + > .dashboard-widget { + background-color: @widgetBackgroundColor; - &:hover { - color: darken(@color, 30%); - } - } -} + a { + color: @linkColor; + text-decoration: none; + border-bottom: 1px dotted #888; -.dashboard-gto.dashboard-controls { - color: @color; - a { color: @color; } - background-color: @pageBackgroundColor; - border: 1px dotted @color; -} + &:hover { + color: darken(@color, 30%); + } + } + } -.dashboard-gto.dashboard-widgetwrapper { /* Import widget styles, using the theme variables */ - @import "../../widgets/annotationChart/_annotationChart.less"; - @import "../../widgets/chart/_chart.less"; - @import "../../widgets/clock/_clock.less"; - @import "../../widgets/header/_header.less"; - @import "../../widgets/html/_html.less"; - @import "../../widgets/iframe/_iframe.less"; - @import "../../widgets/image/_image.less"; - @import "../../widgets/javascript/_javascript.less"; - @import "../../widgets/number/_number.less"; - @import "../../widgets/qrcode/_qrcode.less"; - @import "../../widgets/stoplight/_stoplight.less"; - @import "../../widgets/table/_table.less"; - @import "../../widgets/tableau/_tableau.less"; - @import "../../widgets/treemap/_treemap.less"; - @import "../../widgets/youtube/_youtube.less"; + @import "../_widgets.less"; /* Extra styles */ .table-widget table { @@ -113,6 +93,31 @@ } .table-widget table tr { - border-bottom: 1px dashed #999; + border-bottom: @tableHeaderBorderBottom; + } +} + +/* Transparent Variant */ +.dashboard-widgetwrapper.dashboard-gto.theme-variant-transparent { + > .dashboard-widget { + background-color: transparent; + border: 0px !important; + } +} + +/* Transparent-Unpadded Variant */ +.dashboard-widgetwrapper.dashboard-gto.theme-variant-transparent-unpadded { + > .dashboard-widget { + padding: 0 !important; + background-color: transparent; + border: 0px !important; } } + +.dashboard-gto.dashboard-controls { + color: @color; + a { color: @color; } + background-color: @pageBackgroundColor; + border: 1px dotted @color; +} + diff --git a/cyclotron-site/app/styles/themes/light.less b/cyclotron-site/app/styles/themes/light.less index b54ec1b..aabec16 100644 --- a/cyclotron-site/app/styles/themes/light.less +++ b/cyclotron-site/app/styles/themes/light.less @@ -25,6 +25,7 @@ @headerColor: white; @tableRowHoverBackgroundColor: #efefef; @tableBorderColor: #555; +@tableHeaderBorderBottom: 1px dashed #999; @pageBackgroundColor: white; @widgetBackgroundColor: white; @@ -66,47 +67,25 @@ } /* Widget styles */ -.dashboard-light.dashboard-widgetwrapper > .dashboard-widget { - +.dashboard-widgetwrapper.dashboard-light { color: @color; - background-color: @widgetBackgroundColor; - a { - color: @linkColor; - text-decoration: none; - border-bottom: 1px dotted #888; + > .dashboard-widget { + background-color: @widgetBackgroundColor; - &:hover { - color: darken(@color, 30%); - } - } -} + a { + color: @linkColor; + text-decoration: none; + border-bottom: 1px dotted #888; -.dashboard-light.dashboard-controls { - color: @color; - a { color: @color; } - background-color: @pageBackgroundColor; - border: 1px dotted @color; -} - -.dashboard-light.dashboard-widgetwrapper { + &:hover { + color: darken(@color, 30%); + } + } + } /* Import widget styles, using the theme variables */ - @import "../../widgets/annotationChart/_annotationChart.less"; - @import "../../widgets/chart/_chart.less"; - @import "../../widgets/clock/_clock.less"; - @import "../../widgets/header/_header.less"; - @import "../../widgets/html/_html.less"; - @import "../../widgets/iframe/_iframe.less"; - @import "../../widgets/image/_image.less"; - @import "../../widgets/javascript/_javascript.less"; - @import "../../widgets/number/_number.less"; - @import "../../widgets/qrcode/_qrcode.less"; - @import "../../widgets/stoplight/_stoplight.less"; - @import "../../widgets/table/_table.less"; - @import "../../widgets/tableau/_tableau.less"; - @import "../../widgets/treemap/_treemap.less"; - @import "../../widgets/youtube/_youtube.less"; + @import "../_widgets.less"; /* Extra styles */ .table-widget table th { @@ -119,3 +98,28 @@ } } } + +/* Transparent Variant */ +.dashboard-widgetwrapper.dashboard-light.theme-variant-transparent { + > .dashboard-widget { + background-color: transparent; + box-shadow: none !important; + } +} + +/* Transparent-Unpadded Variant */ +.dashboard-widgetwrapper.dashboard-light.theme-variant-transparent-unpadded { + > .dashboard-widget { + padding: 0 !important; + background-color: transparent; + box-shadow: none !important; + } +} + +.dashboard-light.dashboard-controls { + color: @color; + a { color: @color; } + background-color: @pageBackgroundColor; + border: 1px dotted @color; +} + diff --git a/cyclotron-site/app/styles/themes/lightborderless.less b/cyclotron-site/app/styles/themes/lightborderless.less index 9973a79..c4ad4f9 100644 --- a/cyclotron-site/app/styles/themes/lightborderless.less +++ b/cyclotron-site/app/styles/themes/lightborderless.less @@ -30,6 +30,7 @@ @headerColor: white; @tableRowHoverBackgroundColor: #efefef; @tableBorderColor: #555; +@tableHeaderBorderBottom: 1px dashed #999; /* Dashboard Styles */ .dashboard.dashboard-lightborderless { @@ -64,49 +65,51 @@ } /* Widget styles */ -.dashboard-lightborderless.dashboard-widgetwrapper > .dashboard-widget { - +.dashboard-widgetwrapper.dashboard-lightborderless { color: @color; - background-color: @widgetBackgroundColor; - a { - color: @linkColor; - text-decoration: none; - border-bottom: 1px dotted #888; + > .dashboard-widget { + background-color: @widgetBackgroundColor; - &:hover { - color: darken(@color, 30%); - } - } -} + a { + color: @linkColor; + text-decoration: none; + border-bottom: 1px dotted #888; -.dashboard-lightborderless.dashboard-controls { - color: @color; - a { color: @color; } - background-color: @pageBackgroundColor; - border: 1px dotted @color; -} + &:hover { + color: darken(@color, 30%); + } + } + } -.dashboard-lightborderless.dashboard-widgetwrapper { /* Import widget styles, using the theme variables */ - @import "../../widgets/annotationChart/_annotationChart.less"; - @import "../../widgets/chart/_chart.less"; - @import "../../widgets/clock/_clock.less"; - @import "../../widgets/header/_header.less"; - @import "../../widgets/html/_html.less"; - @import "../../widgets/iframe/_iframe.less"; - @import "../../widgets/image/_image.less"; - @import "../../widgets/javascript/_javascript.less"; - @import "../../widgets/number/_number.less"; - @import "../../widgets/qrcode/_qrcode.less"; - @import "../../widgets/stoplight/_stoplight.less"; - @import "../../widgets/table/_table.less"; - @import "../../widgets/tableau/_tableau.less"; - @import "../../widgets/treemap/_treemap.less"; - @import "../../widgets/youtube/_youtube.less"; + @import "../_widgets.less"; /* Extra styles */ .table-widget table th { font-style: italic; } } + +/* Transparent Variant */ +.dashboard-widgetwrapper.dashboard-lightborderless.theme-variant-transparent { + > .dashboard-widget { + background-color: transparent; + } +} + +/* Transparent-Unpadded Variant */ +.dashboard-widgetwrapper.dashboard-lightborderless.theme-variant-transparent-unpadded { + > .dashboard-widget { + padding: 0 !important; + background-color: transparent; + } +} + + +.dashboard-lightborderless.dashboard-controls { + color: @color; + a { color: @color; } + background-color: @pageBackgroundColor; + border: 1px dotted @color; +} diff --git a/cyclotron-site/app/widgets/chart/chart.jade b/cyclotron-site/app/widgets/chart/chart.jade index d61867f..d09663e 100644 --- a/cyclotron-site/app/widgets/chart/chart.jade +++ b/cyclotron-site/app/widgets/chart/chart.jade @@ -1,11 +1,12 @@ .chart-widget(ng-controller='ChartWidget') h1.title(ng-if='::widget.title') {{ widgetTitle() }} - .widget-loading(spinjs, ng-if='isLoading()') - .widget-error(ng-if='widgetContext.dataSourceError == true && !isLoading()') - .widget-nodata(ng-if='widgetContext.nodata && !isLoading()') - .fa.fa-exclamation-triangle - span {{ widgetContext.nodata }} - - .highchart(ng-if='!widgetContext.nodata && !widgetContext.dataSourceError', - chart='highchart', theme='widget.theme', addshift='widget.addShiftPoints') + .widget-body + .widget-loading(spinjs, ng-if='isLoading()') + .widget-error(ng-if='widgetContext.dataSourceError == true && !isLoading()') + .widget-nodata(ng-if='widgetContext.nodata && !isLoading()') + .fa.fa-exclamation-triangle + span {{ widgetContext.nodata }} + + .highchart(ng-if='!widgetContext.nodata && !widgetContext.dataSourceError', + chart='highchart', theme='widget.theme', addshift='widget.addShiftPoints') diff --git a/cyclotron-site/app/widgets/clock/clock.jade b/cyclotron-site/app/widgets/clock/clock.jade index 61349d1..495b475 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(number-count='1', orientation='"vertical"', class='"orientation-vertical"') + .the-number(number-count='1', is-horizontal='"false"') h1.big {{ currentTime }} diff --git a/cyclotron-site/app/widgets/header/_header.less b/cyclotron-site/app/widgets/header/_header.less index d3d493a..8df2dea 100644 --- a/cyclotron-site/app/widgets/header/_header.less +++ b/cyclotron-site/app/widgets/header/_header.less @@ -19,32 +19,44 @@ height: 100%; .title { + display:flex; + flex-direction: row; + flex-wrap: wrap; a { color: unset; text-decoration: none; border-bottom: none; cursor: unset; + word-wrap: break-word; &.actionable { cursor: pointer } - h1 { - display: inline-block; - } } - .logo { - margin-right: 0.75rem; + a.logo { + flex: 0 0 auto; + img { + margin-right: 0.75rem; + } } - .separator { - margin-left: 0.5rem; - margin-right: 0.5rem; - } + a.title { + flex: 1 1 25rem; + + h1 { + display: inline-block; + } - .page-name { - color: @lighterText; - font-size: 80%; + .separator { + margin-left: 0.5rem; + margin-right: 0.5rem; + } + + .page-name { + color: @lighterText; + font-size: 80%; + } } } diff --git a/cyclotron-site/app/widgets/header/header.jade b/cyclotron-site/app/widgets/header/header.jade index 8bcebf7..6653e3a 100644 --- a/cyclotron-site/app/widgets/header/header.jade +++ b/cyclotron-site/app/widgets/header/header.jade @@ -1,8 +1,10 @@ div.header-widget(ng-controller='HeaderWidget') .title(ng-if='showTitle') - a(ng-href='{{ headerTitle.link }}', ng-class='{ actionable: headerTitle.link }') + a.logo(ng-href='{{ headerTitle.link }}', ng-class='{ actionable: headerTitle.link }') + img(ng-src='{{ headerTitle.logoUrl }}', ng-show='headerTitle.logoUrl', ng-style='{ "height": headerTitle.logoSize }') + a.title(ng-href='{{ headerTitle.link }}', ng-class='{ actionable: headerTitle.link }') h1(ng-style='{ "font-size": headerTitle.titleSize }') - img.logo(ng-src='{{ headerTitle.logoUrl }}', ng-show='headerTitle.logoUrl', ng-style='{ "height": headerTitle.logoSize }') + span {{ title }} span.page-name.separator(ng-if='headerTitle.showPageName') {{ headerTitle.pageNameSeparator }} span.page-name(ng-if='headerTitle.showPageName') {{ page.name }} diff --git a/cyclotron-site/app/widgets/html/html.jade b/cyclotron-site/app/widgets/html/html.jade index 2fa776a..58183bc 100644 --- a/cyclotron-site/app/widgets/html/html.jade +++ b/cyclotron-site/app/widgets/html/html.jade @@ -3,10 +3,11 @@ h1.title(ng-if='::widget.title') {{ widgetTitle() }} - .widget-loading(spinjs, ng-if='isLoading()') - .widget-error(ng-if='widgetContext.dataSourceError == true && !isLoading()') - .widget-nodata(ng-if='widgetContext.nodata && !isLoading()') - .fa.fa-exclamation-triangle - span {{ widgetContext.nodata }} + .widget-body + .widget-loading(spinjs, ng-if='isLoading()') + .widget-error(ng-if='widgetContext.dataSourceError == true && !isLoading()') + .widget-nodata(ng-if='widgetContext.nodata && !isLoading()') + .fa.fa-exclamation-triangle + span {{ widgetContext.nodata }} - div(ng-if='!noDataOrError()', html-repeater='htmlStrings') + div(ng-if='!noDataOrError()', html-repeater='htmlStrings') diff --git a/cyclotron-site/app/widgets/number/_number.less b/cyclotron-site/app/widgets/number/_number.less index abc1e54..c6f8749 100644 --- a/cyclotron-site/app/widgets/number/_number.less +++ b/cyclotron-site/app/widgets/number/_number.less @@ -17,6 +17,9 @@ @footerHeight: 1.4rem; .number-widget { + /* Padding messes up the auto-sizing calculations */ + padding: 0 !important; + overflow-y: auto; overflow-x: hidden; height: 100%; diff --git a/cyclotron-site/app/widgets/table/_table.less b/cyclotron-site/app/widgets/table/_table.less index dfdc56b..d07a9ba 100644 --- a/cyclotron-site/app/widgets/table/_table.less +++ b/cyclotron-site/app/widgets/table/_table.less @@ -24,7 +24,7 @@ } table th { - border-bottom: 1px dashed #999; + border-bottom: @tableHeaderBorderBottom; } table { diff --git a/cyclotron-site/package.json b/cyclotron-site/package.json index 926bd6f..902d193 100644 --- a/cyclotron-site/package.json +++ b/cyclotron-site/package.json @@ -1,7 +1,7 @@ { "name": "cyclotron-site", "description": "Cyclotron: website", - "version": "1.40.0", + "version": "1.41.0", "author": "Dave Bauman ", "license": "MIT", "private": true, diff --git a/cyclotron-svc/config/elasticsearch-events-template.json b/cyclotron-svc/config/elasticsearch-events-template.json index a14676a..318a7e2 100644 --- a/cyclotron-svc/config/elasticsearch-events-template.json +++ b/cyclotron-svc/config/elasticsearch-events-template.json @@ -30,6 +30,22 @@ "sAMAccountName": { "type": "string", "index": "not_analyzed" + }, + "name": { + "type": "string", + "index": "not_analyzed" + } + } + }, + "dashboard": { + "properties": { + "_id": { + "type": "string", + "index": "not_analyzed" + }, + "name": { + "type": "string", + "index": "not_analyzed" } } }, diff --git a/cyclotron-svc/config/elasticsearch-pageviews-template.json b/cyclotron-svc/config/elasticsearch-pageviews-template.json index ea33704..026ee1e 100644 --- a/cyclotron-svc/config/elasticsearch-pageviews-template.json +++ b/cyclotron-svc/config/elasticsearch-pageviews-template.json @@ -32,7 +32,8 @@ "index": "not_analyzed" }, "name": { - "type": "string" + "type": "string", + "index": "not_analyzed" } } }, diff --git a/cyclotron-svc/examples/example-header.json b/cyclotron-svc/examples/example-header.json index 1692b32..d56100c 100644 --- a/cyclotron-svc/examples/example-header.json +++ b/cyclotron-svc/examples/example-header.json @@ -34,7 +34,6 @@ "margin": 10 }, "name": "Awesome Page", - "theme": "lightborderless", "widgets": [{ "allowFullscreen": false, "gridHeight": 1, @@ -48,10 +47,13 @@ "titleSize": "2.5rem" }, "height": "100px", + "parameters": {}, + "themeVariant": "transparent", "widget": "header" }, { "gridHeight": 1, "gridWidth": 1, + "layout": {}, "theme": "light", "widget": "clock" }] @@ -65,7 +67,6 @@ "margin": 10 }, "name": "Another Awesome Page", - "theme": "light", "widgets": [{ "allowFullscreen": false, "gridHeight": 1, @@ -80,7 +81,7 @@ "titleSize": "2.5rem" }, "height": "100px", - "theme": "lightborderless", + "themeVariant": "transparent", "widget": "header" }, { "gridHeight": 1, @@ -113,7 +114,6 @@ "margin": 10 }, "name": "Header With Parameters", - "theme": "light", "widgets": [{ "allowFullscreen": false, "customHtml": "
This chart updates whenever a Parameter is changed, because the Change Event for each Parameter re-executes the Data Source.
", @@ -134,7 +134,7 @@ "parametersIncluded": ["selectedCrime", "showTotal"], "showParameters": true }, - "theme": "lightborderless", + "themeVariant": "transparent", "widget": "header" }, { "dataSource": "uscrime-filtered", @@ -191,6 +191,7 @@ "updateButtonLabel": "Change", "updateEvent": "e = function() {\n // Re-execute the Data Source whenever the button is clicked\n Cyclotron.dataSources['uscrime-filtered2'].execute(true);\n}" }, + "themeVariant": "transparent", "widget": "header" }, { "dataSource": "uscrime-filtered2", @@ -279,7 +280,6 @@ "margin": 10 }, "name": "Header With Separate Parameters", - "theme": "light", "widgets": [{ "allowFullscreen": false, "gridHeight": 1, @@ -295,7 +295,8 @@ }, "height": "85px", "noscroll": true, - "theme": "lightborderless", + "parameters": {}, + "themeVariant": "transparent", "widget": "header" }, { "allowFullscreen": false, @@ -346,7 +347,6 @@ "margin": 10 }, "name": "Header With DateTime Parameters", - "theme": "light", "widgets": [{ "allowFullscreen": false, "customHtml": "
This chart updates whenever a Parameter is changed, because the Change Event for each Parameter re-executes the Data Source.
", @@ -367,7 +367,7 @@ "parametersIncluded": ["datetime", "date", "time"], "showParameters": true }, - "theme": "lightborderless", + "themeVariant": "transparent", "widget": "header" }, { "dataSource": "uscrime-types", @@ -376,7 +376,6 @@ }, "gridHeight": 1, "gridWidth": 1, - "layout": {}, "noData": "No Data", "widget": "chart" }] @@ -389,7 +388,6 @@ "margin": 10 }, "name": "Side Header", - "theme": "light", "widgets": [{ "allowFullscreen": false, "gridHeight": 1, @@ -486,5 +484,8 @@ "name": "time" }], "scripts": [], - "theme": "lightborderless" + "sidebar": { + "showDashboardSidebar": true + }, + "theme": "light" } diff --git a/cyclotron-svc/package.json b/cyclotron-svc/package.json index df3e80d..03e4182 100644 --- a/cyclotron-svc/package.json +++ b/cyclotron-svc/package.json @@ -1,7 +1,7 @@ { "name": "cyclotron-svc", "description": "Cyclotron: REST API", - "version": "1.40.0", + "version": "1.41.0", "author": "Dave Bauman ", "license": "MIT", "private": true, diff --git a/cyclotron-svc/routes/auth.js b/cyclotron-svc/routes/auth.js index e2e2e30..f49d6fe 100644 --- a/cyclotron-svc/routes/auth.js +++ b/cyclotron-svc/routes/auth.js @@ -29,7 +29,7 @@ var config = require('../config/config'), var Sessions = mongoose.model('session'); var getExpiration = function () { - return moment().add(1, 'hour').toDate(); + return moment().add(24, 'hour').toDate(); } /* Removes all Sessions for a given username. */