diff --git a/src/lib/loggers.js b/src/lib/loggers.js index 3524ac2dd27..e6bb04224c9 100644 --- a/src/lib/loggers.js +++ b/src/lib/loggers.js @@ -12,6 +12,8 @@ var dfltConfig = require('../plot_api/plot_config').dfltConfig; +var notifier = require('./notifier'); + var loggers = module.exports = {}; /** @@ -21,39 +23,63 @@ var loggers = module.exports = {}; */ loggers.log = function() { + var i; + if(dfltConfig.logging > 1) { var messages = ['LOG:']; - - for(var i = 0; i < arguments.length; i++) { + for(i = 0; i < arguments.length; i++) { messages.push(arguments[i]); } - apply(console.trace || console.log, messages); } + + if(dfltConfig.notifyOnLogging > 1) { + var lines = []; + for(i = 0; i < arguments.length; i++) { + lines.push(arguments[i]); + } + notifier(lines.join('
'), 'long'); + } }; loggers.warn = function() { + var i; + if(dfltConfig.logging > 0) { var messages = ['WARN:']; - - for(var i = 0; i < arguments.length; i++) { + for(i = 0; i < arguments.length; i++) { messages.push(arguments[i]); } - apply(console.trace || console.log, messages); } + + if(dfltConfig.notifyOnLogging > 0) { + var lines = []; + for(i = 0; i < arguments.length; i++) { + lines.push(arguments[i]); + } + notifier(lines.join('
'), 'stick'); + } }; loggers.error = function() { + var i; + if(dfltConfig.logging > 0) { var messages = ['ERROR:']; - - for(var i = 0; i < arguments.length; i++) { + for(i = 0; i < arguments.length; i++) { messages.push(arguments[i]); } - apply(console.error, messages); } + + if(dfltConfig.notifyOnLogging > 0) { + var lines = []; + for(i = 0; i < arguments.length; i++) { + lines.push(arguments[i]); + } + notifier(lines.join('
'), 'stick'); + } }; /* diff --git a/src/lib/notifier.js b/src/lib/notifier.js index 34d3fe47dfa..89b63ede164 100644 --- a/src/lib/notifier.js +++ b/src/lib/notifier.js @@ -70,11 +70,17 @@ module.exports = function(text, displayLength) { p.append('span').text(lines[i]); } - note.transition() - .duration(700) - .style('opacity', 1) - .transition() - .delay(ts) - .call(killNote); + if(displayLength === 'stick') { + note.transition() + .duration(350) + .style('opacity', 1); + } else { + note.transition() + .duration(700) + .style('opacity', 1) + .transition() + .delay(ts) + .call(killNote); + } }); }; diff --git a/src/plot_api/plot_config.js b/src/plot_api/plot_config.js index 2f2f750332b..87c3d8e4ad7 100644 --- a/src/plot_api/plot_config.js +++ b/src/plot_api/plot_config.js @@ -376,7 +376,9 @@ var configAttributes = { }, logging: { - valType: 'boolean', + valType: 'integer', + min: 0, + max: 2, dflt: 1, description: [ 'Turn all console logging on or off (errors will be thrown)', @@ -388,6 +390,21 @@ var configAttributes = { ].join(' ') }, + notifyOnLogging: { + valType: 'integer', + min: 0, + max: 2, + dflt: 0, + description: [ + 'Set on-graph logging (notifier) level', + 'This should ONLY be set via Plotly.setPlotConfig', + 'Available levels:', + '0: no on-graph logs', + '1: warnings and errors, but not informational messages', + '2: verbose logs' + ].join(' ') + }, + queueLength: { valType: 'integer', min: 0, diff --git a/src/plots/mapbox/index.js b/src/plots/mapbox/index.js index 9efcafca2a0..c9e93b61d6f 100644 --- a/src/plots/mapbox/index.js +++ b/src/plots/mapbox/index.js @@ -250,6 +250,7 @@ function findAccessToken(gd, mapboxIds) { var msg = hasOneSetMapboxStyle ? constants.noAccessTokenErrorMsg : constants.missingStyleErrorMsg; + Lib.error(msg); throw new Error(msg); } diff --git a/test/image/compare_pixels_test.js b/test/image/compare_pixels_test.js index 2ada885b019..f8a1ca22f91 100644 --- a/test/image/compare_pixels_test.js +++ b/test/image/compare_pixels_test.js @@ -102,6 +102,7 @@ if(allMock || argv.filter) { var FLAKY_LIST = [ 'treemap_textposition', + 'treemap_with-without_values_template', 'trace_metatext', 'gl3d_directions-streamtube1' ]; diff --git a/test/jasmine/tests/lib_test.js b/test/jasmine/tests/lib_test.js index cbcdfb2ec18..34d5d2c43a6 100644 --- a/test/jasmine/tests/lib_test.js +++ b/test/jasmine/tests/lib_test.js @@ -1671,8 +1671,9 @@ describe('Test lib.js:', function() { }); describe('loggers', function() { - var stashConsole, - stashLogLevel; + var stashConsole; + var stashLogLevel; + var stashOnGraphLogLevel; function consoleFn(name, hasApply, messages) { var out = function() { @@ -1703,11 +1704,13 @@ describe('Test lib.js:', function() { beforeEach(function() { stashConsole = window.console; stashLogLevel = config.logging; + stashOnGraphLogLevel = config.notifyOnLogging; }); afterEach(function() { window.console = stashConsole; config.logging = stashLogLevel; + config.notifyOnLogging = stashOnGraphLogLevel; }); it('emits one console message if apply is available', function() { @@ -1807,6 +1810,50 @@ describe('Test lib.js:', function() { ['log', [{a: 1, b: 2}]] ]); }); + + describe('should log message in notifier div in accordance notifyOnLogging config option', function() { + var query = '.notifier-note'; + + beforeEach(function(done) { + d3.selectAll(query).each(function() { + d3.select(this).select('button').node().click(); + }); + setTimeout(done, 1000); + }); + + function _run(exp) { + config.logging = 0; + + Lib.log('log'); + Lib.warn('warn'); + Lib.error('error!'); + + var notes = d3.selectAll(query); + + expect(notes.size()).toBe(exp.length, '# of notifier notes'); + + var actual = []; + notes.each(function() { + actual.push(d3.select(this).select('p').text()); + }); + expect(actual).toEqual(exp); + } + + it('with level 2', function() { + config.notifyOnLogging = 2; + _run(['log', 'warn', 'error!']); + }); + + it('with level 1', function() { + config.notifyOnLogging = 1; + _run(['warn', 'error!']); + }); + + it('with level 0', function() { + config.notifyOnLogging = 0; + _run([]); + }); + }); }); describe('keyedContainer', function() { diff --git a/test/jasmine/tests/mapbox_test.js b/test/jasmine/tests/mapbox_test.js index 75d78fc738b..ebe795b20c3 100644 --- a/test/jasmine/tests/mapbox_test.js +++ b/test/jasmine/tests/mapbox_test.js @@ -295,7 +295,7 @@ describe('mapbox credentials', function() { }]); }).toThrow(new Error(constants.missingStyleErrorMsg)); - expect(Lib.error).toHaveBeenCalledTimes(0); + expect(Lib.error).toHaveBeenCalledWith(constants.missingStyleErrorMsg); }, LONG_TIMEOUT_INTERVAL); it('@gl should throw error when setting a Mapbox style w/o a registered token', function() {