Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lens] Manual Annotations #126456

Merged
merged 54 commits into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
472aa2e
Add event annotation service structure
mbondyra Mar 14, 2022
422a231
adding annotation layer to lens. passing event annotation service
mbondyra Mar 14, 2022
308778e
simplify initial Dimensions
mbondyra Mar 14, 2022
6f9a9c9
add annotations to lens
mbondyra Mar 14, 2022
7f2b283
no datasource layer
mbondyra Mar 14, 2022
723d191
group the annotations into numerical icons
mbondyra Mar 15, 2022
af76be3
color icons in tooltip, add the annotation icon, fix date interval bug
mbondyra Mar 16, 2022
b97ba4c
display old time axis for annotations
mbondyra Mar 16, 2022
df2d6d8
error in annotation dimension when date histogram is removed
mbondyra Mar 16, 2022
0d8edbd
refactor: use the same methods for annotations and reference lines
mbondyra Mar 16, 2022
d99ea65
wip
mbondyra Mar 16, 2022
fc451cb
only check activeData for dataLayers
mbondyra Mar 16, 2022
512b09a
added new icons for annotations
mbondyra Mar 16, 2022
f83332c
refactor icons
mbondyra Mar 16, 2022
465a8d1
uniqueLabels
mbondyra Mar 16, 2022
b82c9f4
unique Labels
mbondyra Mar 17, 2022
e9a8b75
diff config from args
mbondyra Mar 17, 2022
fcfe987
change timestamp format
mbondyra Mar 17, 2022
ed3f858
added expression event_annotation_group
mbondyra Mar 17, 2022
437d464
names refactor
mbondyra Mar 17, 2022
653a226
ea service adding help descriptions
mbondyra Mar 19, 2022
3cca99a
rotate icon
mbondyra Mar 19, 2022
b0504f7
added tests
mbondyra Mar 19, 2022
91cf292
fix button problem
mbondyra Mar 19, 2022
30276fe
dnd problem
mbondyra Mar 19, 2022
7d0221a
dnd fix
mbondyra Mar 20, 2022
21b32f8
tests for dimension trigger
mbondyra Mar 21, 2022
0e3bd11
tests for unique labels
mbondyra Mar 21, 2022
9b5c034
[CI] Auto-commit changed files from 'node scripts/build_plugin_list_d…
kibanamachine Mar 21, 2022
471d207
type
mbondyra Mar 21, 2022
8a201b9
add new button test
mbondyra Mar 21, 2022
d4e3cf0
Merge branch 'main' into lens/annotation_service
mbondyra Mar 21, 2022
2a7f1f5
Merge branch 'main' into lens/annotation_service
mbondyra Mar 21, 2022
2a96147
remove noDatasource from config (only needed when initializing a laye…
mbondyra Mar 21, 2022
a87c8a3
addressing Joe's and Michael comments
mbondyra Mar 22, 2022
70ad1cf
Merge commit 'accb6bdf0137652a6d9fb1a0b8619ff64c50740e' into lens/ann…
mbondyra Mar 22, 2022
f7e5c92
remove hexagon and square, address Stratoula's feedback
mbondyra Mar 22, 2022
0c126c4
stroke for icons & icon fill
mbondyra Mar 22, 2022
fd789e4
fix tests
mbondyra Mar 22, 2022
fc618c1
fix small things
mbondyra Mar 22, 2022
64f115c
Merge branch 'main' into lens/annotation_service
mbondyra Mar 22, 2022
75c4214
align the set with tsvb
mbondyra Mar 22, 2022
523af3e
Merge branch 'lens/annotation_service' of github.com:mbondyra/kibana …
mbondyra Mar 22, 2022
b9271ee
align IconSelect
mbondyra Mar 22, 2022
94484dc
fix i18nrc
mbondyra Mar 23, 2022
269e876
Update src/plugins/event_annotation/public/event_annotation_service/i…
mbondyra Mar 23, 2022
115aca7
refactor empty button
mbondyra Mar 23, 2022
2f04298
CR
mbondyra Mar 23, 2022
b8f327b
date cr
mbondyra Mar 23, 2022
0771829
remove DimensionEditorSection
mbondyra Mar 23, 2022
dea3181
Merge commit 'c55bb917fab509df7922ac727d4246514dbd7a59' into lens/ann…
mbondyra Mar 23, 2022
028886a
change to emptyShade for traingle fill
mbondyra Mar 23, 2022
53cc632
Update x-pack/plugins/lens/public/app_plugin/app.scss
mbondyra Mar 23, 2022
6c34ba6
Merge branch 'main' into lens/annotation_service
mbondyra Mar 23, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions .i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"expressions": "src/plugins/expressions",
"expressionShape": "src/plugins/expression_shape",
"expressionTagcloud": "src/plugins/chart_expressions/expression_tagcloud",
"eventAnnotation": "src/plugins/event_annotation",
"fieldFormats": "src/plugins/field_formats",
"flot": "packages/kbn-flot-charts/lib",
"home": "src/plugins/home",
Expand All @@ -50,7 +51,10 @@
"kibana-react": "src/plugins/kibana_react",
"kibanaOverview": "src/plugins/kibana_overview",
"lists": "packages/kbn-securitysolution-list-utils/src",
"management": ["src/legacy/core_plugins/management", "src/plugins/management"],
"management": [
"src/legacy/core_plugins/management",
"src/plugins/management"
],
"monaco": "packages/kbn-monaco/src",
"navigation": "src/plugins/navigation",
"newsfeed": "src/plugins/newsfeed",
Expand All @@ -62,8 +66,13 @@
"sharedUX": "src/plugins/shared_ux",
"sharedUXComponents": "packages/kbn-shared-ux-components/src",
"statusPage": "src/legacy/core_plugins/status_page",
"telemetry": ["src/plugins/telemetry", "src/plugins/telemetry_management_section"],
"timelion": ["src/plugins/vis_types/timelion"],
"telemetry": [
"src/plugins/telemetry",
"src/plugins/telemetry_management_section"
],
"timelion": [
"src/plugins/vis_types/timelion"
],
"uiActions": "src/plugins/ui_actions",
"uiActionsExamples": "examples/ui_action_examples",
"usageCollection": "src/plugins/usage_collection",
Expand All @@ -83,4 +92,4 @@
"visualizations": "src/plugins/visualizations"
},
"translations": []
}
}
4 changes: 4 additions & 0 deletions docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ This API doesn't support angular, for registering angular dev tools, bootstrap a
|This plugin contains reusable code in the form of self-contained modules (or libraries). Each of these modules exports a set of functionality relevant to the domain of the module.


|{kib-repo}blob/{branch}/src/plugins/event_annotation/README.md[eventAnnotation]
|The Event Annotation service contains expressions for event annotations


|{kib-repo}blob/{branch}/src/plugins/expression_error/README.md[expressionError]
|Expression Error plugin adds an error renderer to the expression plugin. The renderer will display the error image.

Expand Down
1 change: 1 addition & 0 deletions packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,4 @@ pageLoadAssetSize:
sessionView: 77750
cloudSecurityPosture: 19109
visTypeGauge: 24113
eventAnnotation: 19334
3 changes: 3 additions & 0 deletions src/plugins/event_annotation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Event Annotation service

The Event Annotation service contains expressions for event annotations
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import type { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { i18n } from '@kbn/i18n';
import type { EventAnnotationOutput } from '../manual_event_annotation/types';

export interface EventAnnotationGroupOutput {
type: 'event_annotation_group';
annotations: EventAnnotationOutput[];
}

export interface EventAnnotationGroupArgs {
annotations: EventAnnotationOutput[];
}

export function eventAnnotationGroup(): ExpressionFunctionDefinition<
'event_annotation_group',
null,
EventAnnotationGroupArgs,
EventAnnotationGroupOutput
> {
return {
name: 'event_annotation_group',
aliases: [],
type: 'event_annotation_group',
inputTypes: ['null'],
help: i18n.translate('eventAnnotation.group.description', {
defaultMessage: 'Event annotation group',
}),
args: {
annotations: {
types: ['manual_event_annotation'],
help: i18n.translate('eventAnnotation.group.args.annotationConfigs', {
defaultMessage: 'Annotation configs',
}),
multi: true,
},
},
fn: (input, args) => {
return {
type: 'event_annotation_group',
annotations: args.annotations,
};
},
};
}
13 changes: 13 additions & 0 deletions src/plugins/event_annotation/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export type { EventAnnotationArgs, EventAnnotationOutput } from './manual_event_annotation/types';
export { manualEventAnnotation } from './manual_event_annotation';
export { eventAnnotationGroup } from './event_annotation_group';
export type { EventAnnotationGroupArgs } from './event_annotation_group';
export type { EventAnnotationConfig } from './types';
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import type { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { i18n } from '@kbn/i18n';
import type { EventAnnotationArgs, EventAnnotationOutput } from './types';
export const manualEventAnnotation: ExpressionFunctionDefinition<
'manual_event_annotation',
null,
EventAnnotationArgs,
EventAnnotationOutput
> = {
name: 'manual_event_annotation',
aliases: [],
type: 'manual_event_annotation',
help: i18n.translate('eventAnnotation.manualAnnotation.description', {
defaultMessage: `Configure manual annotation`,
}),
inputTypes: ['null'],
args: {
time: {
types: ['string'],
help: i18n.translate('eventAnnotation.manualAnnotation.args.time', {
defaultMessage: `Timestamp for annotation`,
}),
},
label: {
types: ['string'],
help: i18n.translate('eventAnnotation.manualAnnotation.args.label', {
defaultMessage: `The name of the annotation`,
}),
},
color: {
types: ['string'],
help: i18n.translate('eventAnnotation.manualAnnotation.args.color', {
defaultMessage: 'The color of the line',
}),
},
lineStyle: {
types: ['string'],
options: ['solid', 'dotted', 'dashed'],
help: i18n.translate('eventAnnotation.manualAnnotation.args.lineStyle', {
defaultMessage: 'The style of the annotation line',
}),
},
lineWidth: {
types: ['number'],
help: i18n.translate('eventAnnotation.manualAnnotation.args.lineWidth', {
defaultMessage: 'The width of the annotation line',
}),
},
icon: {
types: ['string'],
help: i18n.translate('eventAnnotation.manualAnnotation.args.icon', {
defaultMessage: 'An optional icon used for annotation lines',
}),
},
textVisibility: {
types: ['boolean'],
help: i18n.translate('eventAnnotation.manualAnnotation.args.textVisibility', {
defaultMessage: 'Visibility of the label on the annotation line',
}),
},
isHidden: {
types: ['boolean'],
help: i18n.translate('eventAnnotation.manualAnnotation.args.isHidden', {
defaultMessage: `Switch to hide annotation`,
}),
},
},
fn: function fn(input: unknown, args: EventAnnotationArgs) {
return {
type: 'manual_event_annotation',
...args,
};
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { StyleProps } from '../types';

export type EventAnnotationArgs = {
time: string;
} & StyleProps;

export type EventAnnotationOutput = EventAnnotationArgs & { type: 'manual_event_annotation' };
29 changes: 29 additions & 0 deletions src/plugins/event_annotation/common/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export type LineStyle = 'solid' | 'dashed' | 'dotted';
export type AnnotationType = 'manual';
export type KeyType = 'point_in_time';

export interface StyleProps {
label: string;
color?: string;
icon?: string;
lineWidth?: number;
lineStyle?: LineStyle;
textVisibility?: boolean;
isHidden?: boolean;
}

export type EventAnnotationConfig = {
id: string;
key: {
type: KeyType;
timestamp: string;
};
} & StyleProps;
18 changes: 18 additions & 0 deletions src/plugins/event_annotation/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

module.exports = {
preset: '@kbn/test',
rootDir: '../../..',
roots: ['<rootDir>/src/plugins/event_annotation'],
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/src/plugins/event_annotation',
coverageReporters: ['text', 'html'],
collectCoverageFrom: [
'<rootDir>/src/plugins/event_annotation/{common,public,server}/**/*.{ts,tsx}',
],
};
17 changes: 17 additions & 0 deletions src/plugins/event_annotation/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"id": "eventAnnotation",
"version": "kibana",
"server": true,
"ui": true,
"description": "The Event Annotation service contains expressions for event annotations",
"extraPublicDirs": [
"common"
],
"requiredPlugins": [
mbondyra marked this conversation as resolved.
Show resolved Hide resolved
"expressions"
],
"owner": {
"name": "Vis Editors",
"githubTeam": "kibana-vis-editors"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Event Annotation service

The Event Annotation service contains expressions for event annotations
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { euiLightVars } from '@kbn/ui-theme';
export const defaultAnnotationColor = euiLightVars.euiColorAccent;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I probably recommended not to fix the value at the time of import. Maybe geDefaultAnnotationColor = () => euiLightVars.euiColorAccent;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it matter? 🤔

Copy link
Member

@markov00 markov00 Mar 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mbondyra not related to alex suggestion, but to the color: the euiColorAccent differs if you are in dark mode or light mode. in the light theme the color is #F04E98 but is #F68FBE in dark mode.
@MichaelMarcialis ideas?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@markov00 does it matter? Why is it concerning?

Copy link
Contributor

@flash1293 flash1293 Mar 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On switching to dark mode the annotations will still have the light theme color because it's putting the hex value into the saved object. I think that is OK for this PR, it's the same for all of the place where we allow the users to pick a color (series, reference lines and so on). When we discussed this the last time we said we would tackle this problem separately in a general way and apply the same solution to all the places which allow this kind of thing right now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mbondyra not related to alex suggestion, but to the color: the euiColorAccent differs if you are in dark mode or light mode. in the light theme the color is #F04E98 but is #F68FBE in dark mode.
@MichaelMarcialis ideas?

@markov00: That's a good point; something we hadn't considered in our discussion yesterday. Ideally, we would have a single color value that works well for both light and dark modes. Otherwise, the default color is not a purely static value, but a partially dynamic one that changes depending on the theme mode selected when the visualization was created. This could be unexpected or undesirable to users (especially after changing an existing space's theme mode, when sharing/copying visualization across spaces, and in the future when users can set their own theme modes). This is part of the reason why we chose a gray color for the default reference line color, because it works in both theme modes.

In this case, the difference in the color value between light and dark mode presents a similar problem to the one we discussed yesterday if we were to choose black (which would require switching to white in dark mode). That said, because the contrast gap between accent colors in light and dark mode is far lower than the contrast gap between black and white, perhaps we can live with it for now until a more general solution for handling color selection between light/dark themes is addressed, as @flash1293 stated above.

For the sake of the immediate present, I'd say let's either stick with the EUI accent color (regardless of the fact that it will change on visualization creation depending on theme mode), or switch to same gray we use for reference lines as the default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { EventAnnotationServiceType } from './types';

export class EventAnnotationService {
private eventAnnotationService?: EventAnnotationServiceType;
public async getService() {
if (!this.eventAnnotationService) {
const { getEventAnnotationService } = await import('./service');
this.eventAnnotationService = getEventAnnotationService();
}
return this.eventAnnotationService;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { EventAnnotationServiceType } from './types';
import { defaultAnnotationColor } from '..';
mbondyra marked this conversation as resolved.
Show resolved Hide resolved

export function hasIcon(icon: string | undefined): icon is string {
return icon != null && icon !== 'empty';
}

export function getEventAnnotationService(): EventAnnotationServiceType {
return {
toExpression: ({
label,
isHidden,
color,
lineStyle,
lineWidth,
icon,
textVisibility,
time,
}) => {
return {
type: 'expression',
chain: [
{
type: 'function',
function: 'manual_event_annotation',
arguments: {
time: [time],
label: [label],
color: [color || defaultAnnotationColor],
lineWidth: [lineWidth || 1],
lineStyle: [lineStyle || 'solid'],
icon: hasIcon(icon) ? [icon] : ['triangle'],
textVisibility: [textVisibility || false],
isHidden: [Boolean(isHidden)],
},
},
],
};
},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { ExpressionAstExpression } from '../../../expressions/common/ast';
import { EventAnnotationArgs } from '../../common';

export interface EventAnnotationServiceType {
toExpression: (props: EventAnnotationArgs) => ExpressionAstExpression;
}
Loading