Skip to content

Commit

Permalink
[NP] Timelion (#44039) (#46766)
Browse files Browse the repository at this point in the history
* Move index.js to index.ts

* Migrate Vis, interpreter, home and 2 hacks to setup() and start()

* Move Timechart hack to start()

* Add featureCatalogueRegistryProvider to an interface

* Add types to a server param

* Move some .js to .ts

* Add ExpressionFunction<> to interpreter

* Remove Feature Provider

* Remove extra export

* Add an interface to a timelion response

* Add an inteface to the panel

* Add IPrivate interface

* Make nit notes

* Edit uiCapabilities() type

* Shim Timelion plugin

* Shim start() plugin method

* Change InternalCoreStart to LegacyCoreStart

* Move Angular dependencies to a separate module

* Change visualizations import path due to recent changes

* Rename directives

* Take a common property out

* Get rid of require in schema

* Use core.uiSettings

* Refactor timelion request handler

* Remove Private from tests

* Remove redundant dependencies from tests

* Update visualizations paths

* Change expressions paths due to expessions movement

* Refactoring according to reviews

* Add a comment over the uiCapabilities field

* Edit the comment

* Ignore uiCapabilities issue

* Take angular controller out

* Get rid of

* Get rid of config

* Get rid of config in start

* Unwrap handler from redundant promise

* Move npSetup npStart dependencies in a high level

* Rename some details

* Fix reviews

* fix CI

* Take visFactory out
  • Loading branch information
Artyom Gospodarsky authored Sep 27, 2019
1 parent 48ebe3d commit e20fdcb
Show file tree
Hide file tree
Showing 26 changed files with 689 additions and 393 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,40 @@

import { resolve } from 'path';
import { i18n } from '@kbn/i18n';
import { Legacy } from 'kibana';
import { LegacyPluginApi, LegacyPluginInitializer } from 'src/legacy/plugin_discovery/types';
import { CoreSetup, PluginInitializerContext } from 'src/core/server';
import { plugin } from './server';
import { CustomCoreSetup } from './server/plugin';

const experimentalLabel = i18n.translate('timelion.uiSettings.experimentalLabel', {
defaultMessage: 'experimental',
});

export default function (kibana) {
return new kibana.Plugin({
const timelionPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) =>
new Plugin({
require: ['kibana', 'elasticsearch'],

config(Joi) {
config(Joi: any) {
return Joi.object({
enabled: Joi.boolean().default(true),
ui: Joi.object({
enabled: Joi.boolean().default(false),
}).default(),
graphiteUrls: Joi.array().items(
Joi.string().uri({ scheme: ['http', 'https'] }),
).default([]),
graphiteUrls: Joi.array()
.items(Joi.string().uri({ scheme: ['http', 'https'] }))
.default([]),
}).default();
},

// @ts-ignore
// https://github.com/elastic/kibana/pull/44039#discussion_r326582255
uiCapabilities() {
return {
timelion: {
save: true,
},
};
},

publicDir: resolve(__dirname, 'public'),
uiExports: {
app: {
title: 'Timelion',
Expand All @@ -58,11 +62,7 @@ export default function (kibana) {
main: 'plugins/timelion/app',
},
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
hacks: [
'plugins/timelion/hacks/toggle_app_link_in_nav',
'plugins/timelion/lib/panel_registry',
'plugins/timelion/panels/timechart/timechart',
],
hacks: [resolve(__dirname, 'public/legacy')],
injectDefaultVars(server) {
const config = server.config();

Expand All @@ -71,13 +71,6 @@ export default function (kibana) {
kbnIndex: config.get('kibana.index'),
};
},
visTypes: [
'plugins/timelion/vis',
],
interpreter: ['plugins/timelion/timelion_vis_fn'],
home: [
'plugins/timelion/register_feature',
],
mappings: require('./mappings.json'),
uiSettingDefaults: {
'timelion:showTutorial': {
Expand Down Expand Up @@ -159,29 +152,32 @@ export default function (kibana) {
value: '1ms',
description: i18n.translate('timelion.uiSettings.minimumIntervalDescription', {
defaultMessage: 'The smallest interval that will be calculated when using "auto"',
description: '"auto" is a technical value in that context, that should not be translated.',
description:
'"auto" is a technical value in that context, that should not be translated.',
}),
category: ['timelion'],
},
'timelion:graphite.url': {
name: i18n.translate('timelion.uiSettings.graphiteURLLabel', {
defaultMessage: 'Graphite URL',
description: 'The URL should be in the form of https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite',
description:
'The URL should be in the form of https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite',
}),
value: (server) => {
const urls = server.config().get('timelion.graphiteUrls');
value: (server: Legacy.Server) => {
const urls = server.config().get('timelion.graphiteUrls') as string[];
if (urls.length === 0) {
return null;
} else {
return urls[0];
}
},
description: i18n.translate('timelion.uiSettings.graphiteURLDescription', {
defaultMessage: '{experimentalLabel} The <a href="https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite" target="_blank" rel="noopener">URL</a> of your graphite host',
defaultMessage:
'{experimentalLabel} The <a href="https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite" target="_blank" rel="noopener">URL</a> of your graphite host',
values: { experimentalLabel: `<em>[${experimentalLabel}]</em>` },
}),
type: 'select',
options: (server) => (server.config().get('timelion.graphiteUrls')),
options: (server: Legacy.Server) => server.config().get('timelion.graphiteUrls'),
category: ['timelion'],
},
'timelion:quandl.key': {
Expand All @@ -197,11 +193,13 @@ export default function (kibana) {
},
},
},
init: (server) => {
const initializerContext = {};
const core = { http: { server } };
init: (server: Legacy.Server) => {
const initializerContext = {} as PluginInitializerContext;
const core = { http: { server } } as CoreSetup & CustomCoreSetup;

plugin(initializerContext).setup(core);
},
});
}

// eslint-disable-next-line import/no-default-export
export default timelionPluginInitializer;
Original file line number Diff line number Diff line change
Expand Up @@ -18,48 +18,53 @@
*/

import expect from '@kbn/expect';
import ngMock from 'ng_mock';
describe('Tick Generator', function () {
import { generateTicksProvider } from '../panels/timechart/tick_generator';

describe('Tick Generator', function () {
let generateTicks;
const axes = [
{
min: 0,
max: 5000,
delta: 100
},
{
min: 0,
max: 50000,
delta: 2000
},
{
min: 4096,
max: 6000,
delta: 250
}
];
beforeEach(ngMock.module('kibana'));
beforeEach(ngMock.inject(function (Private) {
generateTicks = Private(require('plugins/timelion/panels/timechart/tick_generator'));
}));

it('returns a function', function () {
expect(generateTicks).to.be.a('function');
beforeEach(function () {
generateTicks = generateTicksProvider();
});

describe('generateTicksProvider()', function () {
it('should return a function', function () {
expect(generateTicks).to.be.a('function');
});
});

axes.forEach(axis => {
it(`generates ticks from ${axis.min} to ${axis.max}`, function () {
const ticks = generateTicks(axis);
let n = 1;
while (Math.pow(2, n) < axis.delta) n++;
const expectedDelta = Math.pow(2, n);
const expectedNr = parseInt((axis.max - axis.min) / expectedDelta) + 2;
expect(ticks instanceof Array).to.be(true);
expect(ticks.length).to.be(expectedNr);
expect(ticks[0]).to.equal(axis.min);
expect(ticks[parseInt(ticks.length / 2)]).to.equal(axis.min + expectedDelta * parseInt(ticks.length / 2));
expect(ticks[ticks.length - 1]).to.equal(axis.min + expectedDelta * (ticks.length - 1));
describe('generateTicks()', function () {
const axes = [
{
min: 0,
max: 5000,
delta: 100
},
{
min: 0,
max: 50000,
delta: 2000
},
{
min: 4096,
max: 6000,
delta: 250
}
];

axes.forEach(axis => {
it(`generates ticks from ${axis.min} to ${axis.max}`, function () {
const ticks = generateTicks(axis);
let n = 1;
while (Math.pow(2, n) < axis.delta) n++;
const expectedDelta = Math.pow(2, n);
const expectedNr = parseInt((axis.max - axis.min) / expectedDelta) + 2;
expect(ticks instanceof Array).to.be(true);
expect(ticks.length).to.be(expectedNr);
expect(ticks[0]).to.equal(axis.min);
expect(ticks[parseInt(ticks.length / 2)]).to.equal(axis.min + expectedDelta * parseInt(ticks.length / 2));
expect(ticks[ticks.length - 1]).to.equal(axis.min + expectedDelta * (ticks.length - 1));
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,19 @@
*/

import expect from '@kbn/expect';
import ngMock from 'ng_mock';
describe('Tick Formatters', function () {
import { tickFormatters } from '../../services/tick_formatters';

let tickFormatters;
describe('Tick Formatters', function () {
let formatters;

beforeEach(ngMock.module('kibana'));
beforeEach(ngMock.inject(function (Private) {
tickFormatters = Private(require('plugins/timelion/services/tick_formatters'));
}));
beforeEach(function () {
formatters = tickFormatters();
});

describe('Bits mode', function () {
let bitFormatter;
beforeEach(function () {
bitFormatter = tickFormatters.bits;
bitFormatter = formatters.bits;
});

it('is a function', function () {
Expand All @@ -56,7 +55,7 @@ describe('Tick Formatters', function () {
describe('Bits/s mode', function () {
let bitsFormatter;
beforeEach(function () {
bitsFormatter = tickFormatters['bits/s'];
bitsFormatter = formatters['bits/s'];
});

it('is a function', function () {
Expand All @@ -81,7 +80,7 @@ describe('Tick Formatters', function () {
describe('Bytes mode', function () {
let byteFormatter;
beforeEach(function () {
byteFormatter = tickFormatters.bytes;
byteFormatter = formatters.bytes;
});

it('is a function', function () {
Expand All @@ -106,7 +105,7 @@ describe('Tick Formatters', function () {
describe('Bytes/s mode', function () {
let bytesFormatter;
beforeEach(function () {
bytesFormatter = tickFormatters['bytes/s'];
bytesFormatter = formatters['bytes/s'];
});

it('is a function', function () {
Expand All @@ -131,7 +130,7 @@ describe('Tick Formatters', function () {
describe('Currency mode', function () {
let currencyFormatter;
beforeEach(function () {
currencyFormatter = tickFormatters.currency;
currencyFormatter = formatters.currency;
});

it('is a function', function () {
Expand Down Expand Up @@ -163,7 +162,7 @@ describe('Tick Formatters', function () {
describe('Percent mode', function () {
let percentFormatter;
beforeEach(function () {
percentFormatter = tickFormatters.percent;
percentFormatter = formatters.percent;
});

it('is a function', function () {
Expand Down Expand Up @@ -197,7 +196,7 @@ describe('Tick Formatters', function () {
describe('Custom mode', function () {
let customFormatter;
beforeEach(function () {
customFormatter = tickFormatters.custom;
customFormatter = formatters.custom;
});

it('is a function', function () {
Expand Down
Loading

0 comments on commit e20fdcb

Please sign in to comment.