Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into uptime_tls-settings
Browse files Browse the repository at this point in the history
justinkambic committed Apr 24, 2020
2 parents a1fdf46 + 2ace269 commit a6b014b
Showing 558 changed files with 9,242 additions and 8,226 deletions.
39 changes: 24 additions & 15 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -185,31 +185,40 @@ module.exports = {
zones: [
{
target: [
'src/legacy/**/*',
'x-pack/**/*',
'!x-pack/**/*.test.*',
'!x-pack/test/**/*',
'(src|x-pack)/legacy/**/*',
'(src|x-pack)/plugins/**/(public|server)/**/*',
'src/core/(public|server)/**/*',
'examples/**/*',
],
from: [
'src/core/public/**/*',
'!src/core/public/index.ts',
'!src/core/public/mocks.ts',
'!src/core/public/*.test.mocks.ts',
'!src/core/public/index.ts', // relative import
'!src/core/public/mocks{,.ts}',
'!src/core/server/types{,.ts}',
'!src/core/public/utils/**/*',
'!src/core/public/*.test.mocks{,.ts}',

'src/core/server/**/*',
'!src/core/server/index.ts',
'!src/core/server/mocks.ts',
'!src/core/server/types.ts',
'!src/core/server/test_utils.ts',
'!src/core/server/index.ts', // relative import
'!src/core/server/mocks{,.ts}',
'!src/core/server/types{,.ts}',
'!src/core/server/test_utils',
// for absolute imports until fixed in
// https://github.com/elastic/kibana/issues/36096
'!src/core/server/types',
'!src/core/server/*.test.mocks.ts',

'!src/core/server/*.test.mocks{,.ts}',
],
allowSameFolder: true,
errorMessage:
'Plugins may only import from top-level public and server modules in core.',
},
{
target: [
'(src|x-pack)/legacy/**/*',
'(src|x-pack)/plugins/**/(public|server)/**/*',
'examples/**/*',
'!(src|x-pack)/**/*.test.*',
'!(x-pack/)?test/**/*',
],
from: [
'(src|x-pack)/plugins/**/(public|server)/**/*',
'!(src|x-pack)/plugins/**/(public|server)/(index|mocks).{js,ts,tsx}',
],
1 change: 1 addition & 0 deletions .github/CODEOWNERS
This CODEOWNERS file contains errors

CODEOWNERS errors

  • Unknown owner on line 6: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/lens/ @elastic/kibana-app
  • Unknown owner on line 7: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/graph/ @elastic/kibana-app
  • Unknown owner on line 8: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …legacy/server/url_shortening/ @elastic/kibana-app
  • Unknown owner on line 9: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …rc/legacy/server/sample_data/ @elastic/kibana-app
  • Unknown owner on line 10: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …gins/kibana/public/dashboard/ @elastic/kibana-app
  • Unknown owner on line 11: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …ugins/kibana/public/discover/ @elastic/kibana-app
  • Unknown owner on line 12: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …ic/local_application_service/ @elastic/kibana-app
  • Unknown owner on line 13: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …gins/kibana/public/dev_tools/ @elastic/kibana-app
  • Unknown owner on line 14: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …core_plugins/vis_type_vislib/ @elastic/kibana-app
  • Unknown owner on line 15: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    /src/plugins/vis_type_xy/ @elastic/kibana-app
  • Unknown owner on line 16: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    /src/plugins/vis_type_table/ @elastic/kibana-app
  • Unknown owner on line 17: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    /src/plugins/kibana_legacy/ @elastic/kibana-app
  • Unknown owner on line 18: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …rc/plugins/vis_type_timelion/ @elastic/kibana-app
  • Unknown owner on line 19: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    /src/plugins/dashboard/ @elastic/kibana-app
  • Unknown owner on line 20: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    /src/plugins/discover/ @elastic/kibana-app
  • Unknown owner on line 21: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …rc/plugins/input_control_vis/ @elastic/kibana-app
  • Unknown owner on line 22: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    /src/plugins/visualize/ @elastic/kibana-app
  • Unknown owner on line 23: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …/plugins/vis_type_timeseries/ @elastic/kibana-app
  • Unknown owner on line 24: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    /src/plugins/vis_type_metric/ @elastic/kibana-app
  • Unknown owner on line 25: make sure the team @elastic/kibana-app exists, is publicly visible, and has write access to the repository
    …rc/plugins/vis_type_markdown/ @elastic/kibana-app
  • Unknown owner on line 29: make sure the team @elastic/kibana-core-ui exists, is publicly visible, and has write access to the repository
    /src/plugins/home/public @elastic/kibana-core-ui
  • Unknown owner on line 30: make sure the team @elastic/kibana-core-ui exists, is publicly visible, and has write access to the repository
    /src/plugins/home/server/*.ts @elastic/kibana-core-ui
  • Unknown owner on line 31: make sure the team @elastic/kibana-core-ui exists, is publicly visible, and has write access to the repository
    …plugins/home/server/services/ @elastic/kibana-core-ui
  • Unknown owner on line 33: make sure the team @elastic/kibana-core-ui exists, is publicly visible, and has write access to the repository
    …ugins/kibana/public/home/*.ts @elastic/kibana-core-ui
  • Unknown owner on line 34: make sure the team @elastic/kibana-core-ui exists, is publicly visible, and has write access to the repository
    …ins/kibana/public/home/*.scss @elastic/kibana-core-ui
  • Unknown owner on line 35: make sure the team @elastic/kibana-core-ui exists, is publicly visible, and has write access to the repository
    …/kibana/public/home/np_ready/ @elastic/kibana-core-ui
  • Unknown owner on line 38: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …ples/url_generators_examples/ @elastic/kibana-app-arch
  • Unknown owner on line 39: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …ples/url_generators_explorer/ @elastic/kibana-app-arch
  • Unknown owner on line 40: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /packages/kbn-interpreter/ @elastic/kibana-app-arch
  • Unknown owner on line 41: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …/core_plugins/embeddable_api/ @elastic/kibana-app-arch
  • Unknown owner on line 42: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …acy/core_plugins/interpreter/ @elastic/kibana-app-arch
  • Unknown owner on line 43: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …cy/core_plugins/kibana_react/ @elastic/kibana-app-arch
  • Unknown owner on line 44: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …ins/kibana/public/management/ @elastic/kibana-app-arch
  • Unknown owner on line 45: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …server/routes/api/management/ @elastic/kibana-app-arch
  • Unknown owner on line 46: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …/core_plugins/visualizations/ @elastic/kibana-app-arch
  • Unknown owner on line 47: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …legacy/server/index_patterns/ @elastic/kibana-app-arch
  • Unknown owner on line 48: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …rc/plugins/advanced_settings/ @elastic/kibana-app-arch
  • Unknown owner on line 49: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/bfetch/ @elastic/kibana-app-arch
  • Unknown owner on line 50: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/data/ @elastic/kibana-app-arch
  • Unknown owner on line 51: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/embeddable/ @elastic/kibana-app-arch
  • Unknown owner on line 52: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/expressions/ @elastic/kibana-app-arch
  • Unknown owner on line 53: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/inspector/ @elastic/kibana-app-arch
  • Unknown owner on line 54: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/kibana_react/ @elastic/kibana-app-arch
  • Unknown owner on line 55: make sure the team @elastic/kibana-canvas exists, is publicly visible, and has write access to the repository
    …bana_react/public/code_editor @elastic/kibana-canvas
  • Unknown owner on line 56: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/kibana_utils/ @elastic/kibana-app-arch
  • Unknown owner on line 57: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/management/ @elastic/kibana-app-arch
  • Unknown owner on line 58: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/navigation/ @elastic/kibana-app-arch
  • Unknown owner on line 59: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/share/ @elastic/kibana-app-arch
  • Unknown owner on line 60: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/ui_actions/ @elastic/kibana-app-arch
  • Unknown owner on line 61: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /src/plugins/visualizations/ @elastic/kibana-app-arch
  • Unknown owner on line 62: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …/plugins/advanced_ui_actions/ @elastic/kibana-app-arch
  • Unknown owner on line 63: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    …x-pack/plugins/data_enhanced/ @elastic/kibana-app-arch
  • Unknown owner on line 64: make sure the team @elastic/kibana-app-arch exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/drilldowns/ @elastic/kibana-app-arch
  • Unknown owner on line 72: make sure @watson exists and has write access to the repository
    /src/apm.js @watson
  • Unknown owner on line 75: make sure the team @elastic/beats exists, is publicly visible, and has write access to the repository
    …cy/plugins/beats_management/  @elastic/beats
  • Unknown owner on line 78: make sure the team @elastic/kibana-canvas exists, is publicly visible, and has write access to the repository
    …-pack/legacy/plugins/canvas/  @elastic/kibana-canvas
  • Unknown owner on line 81: make sure the team @elastic/logs-metrics-ui exists, is publicly visible, and has write access to the repository
    /x-pack/legacy/plugins/infra/ @elastic/logs-metrics-ui
  • Unknown owner on line 82: make sure the team @elastic/logs-metrics-ui exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/infra/ @elastic/logs-metrics-ui
  • Unknown owner on line 83: make sure the team @elastic/ingest-management exists, is publicly visible, and has write access to the repository
    …-pack/plugins/ingest_manager/ @elastic/ingest-management
  • Unknown owner on line 84: make sure the team @elastic/ingest-management exists, is publicly visible, and has write access to the repository
    …egacy/plugins/ingest_manager/ @elastic/ingest-management
  • Unknown owner on line 85: make sure the team @elastic/ingest-management exists, is publicly visible, and has write access to the repository
    …lastic/apm-ui @elastic/uptime @elastic/ingest-management
  • Unknown owner on line 85: make sure the team @elastic/logs-metrics-ui exists, is publicly visible, and has write access to the repository
    …x-pack/plugins/observability/ @elastic/logs-metrics-ui @elastic/apm-ui @elastic/uptime @elastic/ingest-management
  • Unknown owner on line 86: make sure the team @elastic/stack-monitoring-ui exists, is publicly visible, and has write access to the repository
    …ck/legacy/plugins/monitoring/ @elastic/stack-monitoring-ui
  • Unknown owner on line 130: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    /src/core/  @elastic/kibana-platform
  • Unknown owner on line 131: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    /config/kibana.yml @elastic/kibana-platform
  • Unknown owner on line 132: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/features/  @elastic/kibana-platform
  • Unknown owner on line 133: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/licensing/  @elastic/kibana-platform
  • Unknown owner on line 134: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    /packages/kbn-config-schema/ @elastic/kibana-platform
  • Unknown owner on line 135: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    /src/legacy/server/config/ @elastic/kibana-platform
  • Unknown owner on line 136: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    /src/legacy/server/http/ @elastic/kibana-platform
  • Unknown owner on line 137: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    /src/legacy/server/logging/ @elastic/kibana-platform
  • Unknown owner on line 138: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    …legacy/server/saved_objects/  @elastic/kibana-platform
  • Unknown owner on line 139: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    /src/legacy/server/status/ @elastic/kibana-platform
  • Unknown owner on line 140: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    /src/plugins/status_page/ @elastic/kibana-platform
  • Unknown owner on line 141: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    …ins/saved_objects_management/ @elastic/kibana-platform
  • Unknown owner on line 142: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    …heck_published_api_changes.ts @elastic/kibana-platform
  • Unknown owner on line 145: make sure the team @elastic/kibana-platform exists, is publicly visible, and has write access to the repository
    …sp/  @elastic/kibana-security @elastic/kibana-platform
  • Unknown owner on line 161: make sure the team @elastic/pulse exists, is publicly visible, and has write access to the repository
    /packages/kbn-analytics/ @elastic/pulse
  • Unknown owner on line 162: make sure the team @elastic/pulse exists, is publicly visible, and has write access to the repository
    …egacy/core_plugins/ui_metric/ @elastic/pulse
  • Unknown owner on line 163: make sure the team @elastic/pulse exists, is publicly visible, and has write access to the repository
    /src/plugins/telemetry/ @elastic/pulse
  • Unknown owner on line 164: make sure the team @elastic/pulse exists, is publicly visible, and has write access to the repository
    …telemetry_collection_manager/ @elastic/pulse
  • Unknown owner on line 165: make sure the team @elastic/pulse exists, is publicly visible, and has write access to the repository
    …telemetry_management_section/ @elastic/pulse
  • Unknown owner on line 166: make sure the team @elastic/pulse exists, is publicly visible, and has write access to the repository
    …src/plugins/usage_collection/ @elastic/pulse
  • Unknown owner on line 167: make sure the team @elastic/pulse exists, is publicly visible, and has write access to the repository
    …s/telemetry_collection_xpack/ @elastic/pulse
  • Unknown owner on line 170: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    …pack/legacy/plugins/alerting/ @elastic/kibana-alerting-services
  • Unknown owner on line 171: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    …-pack/legacy/plugins/actions/ @elastic/kibana-alerting-services
  • Unknown owner on line 172: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/alerting/ @elastic/kibana-alerting-services
  • Unknown owner on line 173: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/actions/ @elastic/kibana-alerting-services
  • Unknown owner on line 174: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/event_log/ @elastic/kibana-alerting-services
  • Unknown owner on line 175: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/task_manager/ @elastic/kibana-alerting-services
  • Unknown owner on line 176: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    …est/alerting_api_integration/ @elastic/kibana-alerting-services
  • Unknown owner on line 177: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    …gration/plugins/task_manager/ @elastic/kibana-alerting-services
  • Unknown owner on line 178: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    …ion/test_suites/task_manager/ @elastic/kibana-alerting-services
  • Unknown owner on line 179: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    …/plugins/triggers_actions_ui/ @elastic/kibana-alerting-services
  • Unknown owner on line 180: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    …/plugins/triggers_actions_ui/ @elastic/kibana-alerting-services
  • Unknown owner on line 181: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    …ssl/apps/triggers_actions_ui/ @elastic/kibana-alerting-services
  • Unknown owner on line 182: make sure the team @elastic/kibana-alerting-services exists, is publicly visible, and has write access to the repository
    …_ssl/fixtures/plugins/alerts/ @elastic/kibana-alerting-services
  • Unknown owner on line 188: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    /src/plugins/dev_tools/ @elastic/es-ui
  • Unknown owner on line 189: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    /src/plugins/console/  @elastic/es-ui
  • Unknown owner on line 190: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    /src/plugins/es_ui_shared/  @elastic/es-ui
  • Unknown owner on line 191: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …s/cross_cluster_replication/  @elastic/es-ui
  • Unknown owner on line 192: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …/index_lifecycle_management/  @elastic/es-ui
  • Unknown owner on line 193: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …cy/plugins/index_management/  @elastic/es-ui
  • Unknown owner on line 194: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …/plugins/license_management/  @elastic/es-ui
  • Unknown owner on line 195: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …-pack/legacy/plugins/rollup/  @elastic/es-ui
  • Unknown owner on line 196: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …cy/plugins/snapshot_restore/  @elastic/es-ui
  • Unknown owner on line 197: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …y/plugins/upgrade_assistant/  @elastic/es-ui
  • Unknown owner on line 198: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …/plugins/console_extensions/  @elastic/es-ui
  • Unknown owner on line 199: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …x-pack/plugins/es_ui_shared/  @elastic/es-ui
  • Unknown owner on line 200: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …x-pack/plugins/grokdebugger/  @elastic/es-ui
  • Unknown owner on line 201: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …ck/plugins/index_management/  @elastic/es-ui
  • Unknown owner on line 202: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …/plugins/license_management/  @elastic/es-ui
  • Unknown owner on line 203: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …x-pack/plugins/painless_lab/  @elastic/es-ui
  • Unknown owner on line 204: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …ack/plugins/remote_clusters/  @elastic/es-ui
  • Unknown owner on line 205: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/rollup/  @elastic/es-ui
  • Unknown owner on line 206: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …pack/plugins/searchprofiler/  @elastic/es-ui
  • Unknown owner on line 207: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …ck/plugins/snapshot_restore/  @elastic/es-ui
  • Unknown owner on line 208: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    …k/plugins/upgrade_assistant/  @elastic/es-ui
  • Unknown owner on line 209: make sure the team @elastic/es-ui exists, is publicly visible, and has write access to the repository
    /x-pack/plugins/watcher/  @elastic/es-ui
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@
/src/plugins/vis_type_timelion/ @elastic/kibana-app
/src/plugins/dashboard/ @elastic/kibana-app
/src/plugins/discover/ @elastic/kibana-app
/src/plugins/input_control_vis/ @elastic/kibana-app
/src/plugins/visualize/ @elastic/kibana-app
/src/plugins/vis_type_timeseries/ @elastic/kibana-app
/src/plugins/vis_type_metric/ @elastic/kibana-app
4 changes: 2 additions & 2 deletions .i18nrc.json
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
"esUi": "src/plugins/es_ui_shared",
"devTools": "src/plugins/dev_tools",
"expressions": "src/plugins/expressions",
"inputControl": "src/legacy/core_plugins/input_control_vis",
"inputControl": "src/plugins/input_control_vis",
"inspector": "src/plugins/inspector",
"inspectorViews": "src/legacy/core_plugins/inspector_views",
"interpreter": "src/legacy/core_plugins/interpreter",
@@ -51,7 +51,7 @@
"visTypeTable": "src/plugins/vis_type_table",
"visTypeTagCloud": "src/plugins/vis_type_tagcloud",
"visTypeTimeseries": ["src/legacy/core_plugins/vis_type_timeseries", "src/plugins/vis_type_timeseries"],
"visTypeVega": "src/legacy/core_plugins/vis_type_vega",
"visTypeVega": "src/plugins/vis_type_vega",
"visTypeVislib": "src/legacy/core_plugins/vis_type_vislib",
"visTypeXy": "src/legacy/core_plugins/vis_type_xy",
"visualizations": "src/plugins/visualizations",

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -2,21 +2,12 @@

[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigOptions](./kibana-plugin-plugins-data-public.aggconfigoptions.md)

## AggConfigOptions interface
## AggConfigOptions type

<b>Signature:</b>

```typescript
export interface AggConfigOptions
export declare type AggConfigOptions = Assign<AggConfigSerialized, {
type: IAggType;
}>;
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [enabled](./kibana-plugin-plugins-data-public.aggconfigoptions.enabled.md) | <code>boolean</code> | |
| [id](./kibana-plugin-plugins-data-public.aggconfigoptions.id.md) | <code>string</code> | |
| [params](./kibana-plugin-plugins-data-public.aggconfigoptions.params.md) | <code>Record&lt;string, any&gt;</code> | |
| [schema](./kibana-plugin-plugins-data-public.aggconfigoptions.schema.md) | <code>string</code> | |
| [type](./kibana-plugin-plugins-data-public.aggconfigoptions.type.md) | <code>IAggType</code> | |

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -7,5 +7,5 @@
<b>Signature:</b>

```typescript
makeAgg: (agg: TAggConfig, state?: any) => TAggConfig;
makeAgg: (agg: TAggConfig, state?: AggConfigSerialized) => TAggConfig;
```
Original file line number Diff line number Diff line change
@@ -21,5 +21,5 @@ export declare class AggParamType<TAggConfig extends IAggConfig = IAggConfig> ex
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [allowedAggs](./kibana-plugin-plugins-data-public.aggparamtype.allowedaggs.md) | | <code>string[]</code> | |
| [makeAgg](./kibana-plugin-plugins-data-public.aggparamtype.makeagg.md) | | <code>(agg: TAggConfig, state?: any) =&gt; TAggConfig</code> | |
| [makeAgg](./kibana-plugin-plugins-data-public.aggparamtype.makeagg.md) | | <code>(agg: TAggConfig, state?: AggConfigSerialized) =&gt; TAggConfig</code> | |
Original file line number Diff line number Diff line change
@@ -7,5 +7,5 @@
<b>Signature:</b>

```typescript
baseFormattersPublic: (import("../../common").IFieldFormatType | typeof DateFormat)[]
baseFormattersPublic: (import("../../common").FieldFormatInstanceType | typeof DateFormat)[]
```
Original file line number Diff line number Diff line change
@@ -49,7 +49,6 @@

| Interface | Description |
| --- | --- |
| [AggConfigOptions](./kibana-plugin-plugins-data-public.aggconfigoptions.md) | |
| [AggParamOption](./kibana-plugin-plugins-data-public.aggparamoption.md) | |
| [DataPublicPluginSetup](./kibana-plugin-plugins-data-public.datapublicpluginsetup.md) | |
| [DataPublicPluginStart](./kibana-plugin-plugins-data-public.datapublicpluginstart.md) | |
@@ -118,6 +117,7 @@

| Type Alias | Description |
| --- | --- |
| [AggConfigOptions](./kibana-plugin-plugins-data-public.aggconfigoptions.md) | |
| [AggParam](./kibana-plugin-plugins-data-public.aggparam.md) | |
| [CustomFilter](./kibana-plugin-plugins-data-public.customfilter.md) | |
| [EsQuerySortValue](./kibana-plugin-plugins-data-public.esquerysortvalue.md) | |
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
```typescript
setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies): {
fieldFormats: {
register: (customFieldFormat: import("../common").IFieldFormatType) => number;
register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number;
};
search: ISearchSetup;
};
@@ -26,7 +26,7 @@ setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies): {

`{
fieldFormats: {
register: (customFieldFormat: import("../common").IFieldFormatType) => number;
register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number;
};
search: ISearchSetup;
}`
Binary file added docs/images/report-automate-csv.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/report-automate-pdf.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 2 additions & 3 deletions docs/user/alerting/pre-configured-connectors.asciidoc
Original file line number Diff line number Diff line change
@@ -20,8 +20,7 @@ action are predefined, including the connector name and ID.

The following example shows a valid configuration 2 out-of-the box connector.

[source,console]
------------------------
```js
xpack.actions.preconfigured:
- id: 'my-slack1' <1>
actionTypeId: .slack <2>
@@ -40,7 +39,7 @@ The following example shows a valid configuration 2 out-of-the box connector.
secrets: <5>
user: elastic
password: changeme
------------------------
```

<1> `id` is the action connector identifier.
<2> `actionTypeId` is the action type identifier.
42 changes: 26 additions & 16 deletions docs/user/reporting/automating-report-generation.asciidoc
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
[role="xpack"]
[[automating-report-generation]]
== Automating report generation
You can automatically generate reports with {watcher}, or by submitting
HTTP `POST` requests from a script.
Automatically generate PDF and CSV reports by submitting HTTP `POST` requests using {watcher} or a script.

include::report-intervals.asciidoc[]

[float]
=== Get the POST URL
=== Create a POST URL

Generating a report either through {watcher} or a script requires capturing the **POST
URL**, which is the URL to queue a report for generation.
Create the POST
URL that triggers a report to generate.

To get the URL for triggering PDF report generation during a given time period:
To create the POST URL for PDF reports:

. Load the saved object in *Visualize* or *Dashboard*.
. To specify a relative or absolute time period, use the time filter.
. In the {kib} toolbar, click *Share*.
. Select *PDF Reports*.
. Click **Copy POST URL**.
. Go to *Visualize* or *Dashboard*, then open the visualization or dashboard.
+
To specify a relative or absolute time period, use the time filter.

To get the URL for triggering CSV report generation during a given time period:
. From the {kib} toolbar, click *Share*, then select *PDF Reports*.

. Click *Copy POST URL*.
+
[role="screenshot"]
image::images/report-automate-pdf.png[Generate Visualize and Dashboard reports]


To create the POST URL for CSV reports:

. Load the saved search in *Discover*.
. To specify a relative or absolute time period, use the time filter.
. In the {kib} toolbar, click *Share*.
. Select *CSV Reports*.
. Click **Copy POST URL**.
+
To specify a relative or absolute time period, use the time filter.

. From the {kib} toolbar, click *Share*, then select *CSV Reports*.

. Click *Copy POST URL*.
+
[role="screenshot"]
image::images/report-automate-csv.png[Generate Discover reports]

[float]
=== Use Watcher
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -120,7 +120,7 @@
"@babel/core": "^7.9.0",
"@babel/register": "^7.9.0",
"@elastic/apm-rum": "^5.1.1",
"@elastic/charts": "18.3.0",
"@elastic/charts": "18.4.1",
"@elastic/datemath": "5.0.3",
"@elastic/ems-client": "7.8.0",
"@elastic/eui": "22.3.0",
3 changes: 2 additions & 1 deletion packages/kbn-babel-preset/package.json
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
"babel-plugin-add-module-exports": "^1.0.2",
"babel-plugin-filter-imports": "^3.0.0",
"babel-plugin-styled-components": "^1.10.6",
"babel-plugin-transform-define": "^1.3.1"
"babel-plugin-transform-define": "^1.3.1",
"babel-plugin-transform-imports": "^2.0.0"
}
}
19 changes: 19 additions & 0 deletions packages/kbn-babel-preset/webpack_preset.js
Original file line number Diff line number Diff line change
@@ -42,5 +42,24 @@ module.exports = () => {
},
],
],
// NOTE: we can enable this by default for everything as soon as we only have one instance
// of lodash across the entire project. For now we are just enabling it for siem
// as they are extensively using the lodash v4
overrides: [
{
test: [/x-pack[\/\\]legacy[\/\\]plugins[\/\\]siem[\/\\]public/],
plugins: [
[
require.resolve('babel-plugin-transform-imports'),
{
'lodash/?(((\\w*)?/?)*)': {
transform: 'lodash/${1}/${member}',
preventFullImport: false,
},
},
],
],
},
],
};
};

Large diffs are not rendered by default.

14 changes: 11 additions & 3 deletions packages/kbn-optimizer/src/worker/webpack.config.ts
Original file line number Diff line number Diff line change
@@ -34,7 +34,6 @@ import { Bundle, WorkerConfig, parseDirPath, DisallowedSyntaxPlugin } from '../c

const IS_CODE_COVERAGE = !!process.env.CODE_COVERAGE;
const ISTANBUL_PRESET_PATH = require.resolve('@kbn/babel-preset/istanbul_preset');
const PUBLIC_PATH_PLACEHOLDER = '__REPLACE_WITH_PUBLIC_PATH__';
const BABEL_PRESET_PATH = require.resolve('@kbn/babel-preset/webpack_preset');

const STATIC_BUNDLE_PLUGINS = [
@@ -105,7 +104,6 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) {
output: {
path: bundle.outputDir,
filename: `[name].${bundle.type}.js`,
publicPath: PUBLIC_PATH_PLACEHOLDER,
devtoolModuleFilenameTemplate: info =>
`/${bundle.type}:${bundle.id}/${Path.relative(
bundle.sourceRoot,
@@ -140,12 +138,22 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) {

module: {
// no parse rules for a few known large packages which have no require() statements
// or which have require() statements that should be ignored because the file is
// already bundled with all its necessary depedencies
noParse: [
/[\///]node_modules[\///]elasticsearch-browser[\///]/,
/[\///]node_modules[\///]lodash[\///]index\.js/,
/[\///]node_modules[\///]lodash[\///]index\.js$/,
/[\///]node_modules[\///]vega-lib[\///]build[\///]vega\.js$/,
],

rules: [
{
include: Path.join(bundle.contextDir, bundle.entry),
loader: UiSharedDeps.publicPathLoader,
options: {
key: bundle.id,
},
},
{
test: /\.css$/,
include: /node_modules/,
5 changes: 5 additions & 0 deletions packages/kbn-ui-shared-deps/index.d.ts
Original file line number Diff line number Diff line change
@@ -53,3 +53,8 @@ export const lightCssDistFilename: string;
export const externals: {
[key: string]: string;
};

/**
* Webpack loader for configuring the public path lookup from `window.__kbnPublicPath__`.
*/
export const publicPathLoader: string;
1 change: 1 addition & 0 deletions packages/kbn-ui-shared-deps/index.js
Original file line number Diff line number Diff line change
@@ -64,3 +64,4 @@ exports.externals = {
'elasticsearch-browser': '__kbnSharedDeps__.ElasticsearchBrowser',
'elasticsearch-browser/elasticsearch': '__kbnSharedDeps__.ElasticsearchBrowser',
};
exports.publicPathLoader = require.resolve('./public_path_loader');
2 changes: 1 addition & 1 deletion packages/kbn-ui-shared-deps/package.json
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
"kbn:watch": "node scripts/build --watch"
},
"dependencies": {
"@elastic/charts": "18.3.0",
"@elastic/charts": "18.4.1",
"@elastic/eui": "22.3.0",
"@kbn/i18n": "1.0.0",
"abortcontroller-polyfill": "^1.4.0",
23 changes: 23 additions & 0 deletions packages/kbn-ui-shared-deps/public_path_loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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.
*/

module.exports = function(source) {
const options = this.query;
return `__webpack_public_path__ = window.__kbnPublicPath__['${options.key}'];${source}`;
};
12 changes: 11 additions & 1 deletion packages/kbn-ui-shared-deps/webpack.config.js
Original file line number Diff line number Diff line change
@@ -46,7 +46,6 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({
path: UiSharedDeps.distDir,
filename: '[name].js',
sourceMapFilename: '[file].map',
publicPath: '__REPLACE_WITH_PUBLIC_PATH__',
devtoolModuleFilenameTemplate: info =>
`kbn-ui-shared-deps/${Path.relative(REPO_ROOT, info.absoluteResourcePath)}`,
library: '__kbnSharedDeps__',
@@ -55,6 +54,17 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({
module: {
noParse: [MOMENT_SRC],
rules: [
{
include: [require.resolve('./entry.js')],
use: [
{
loader: UiSharedDeps.publicPathLoader,
options: {
key: 'kbn-ui-shared-deps',
},
},
],
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
1 change: 1 addition & 0 deletions src/core/public/http/index.ts
Original file line number Diff line number Diff line change
@@ -18,4 +18,5 @@
*/

export { HttpService } from './http_service';
export { HttpFetchError } from './http_fetch_error';
export * from './types';
1 change: 1 addition & 0 deletions src/core/public/index.ts
Original file line number Diff line number Diff line change
@@ -143,6 +143,7 @@ export {
export {
HttpHeadersInit,
HttpRequestInit,
HttpFetchError,
HttpFetchOptions,
HttpFetchOptionsWithPath,
HttpFetchQuery,
17 changes: 17 additions & 0 deletions src/core/public/public.api.md
Original file line number Diff line number Diff line change
@@ -593,6 +593,23 @@ export type HandlerFunction<T extends object> = (context: T, ...args: any[]) =>
// @public
export type HandlerParameters<T extends HandlerFunction<any>> = T extends (context: any, ...args: infer U) => any ? U : never;

// @internal (undocumented)
export class HttpFetchError extends Error implements IHttpFetchError {
constructor(message: string, name: string, request: Request, response?: Response | undefined, body?: any);
// (undocumented)
readonly body?: any;
// (undocumented)
readonly name: string;
// (undocumented)
readonly req: Request;
// (undocumented)
readonly request: Request;
// (undocumented)
readonly res?: Response;
// (undocumented)
readonly response?: Response | undefined;
}

// @public
export interface HttpFetchOptions extends HttpRequestInit {
asResponse?: boolean;
1 change: 1 addition & 0 deletions src/core/server/mocks.ts
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ export { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.
export { httpServiceMock } from './http/http_service.mock';
export { loggingServiceMock } from './logging/logging_service.mock';
export { savedObjectsRepositoryMock } from './saved_objects/service/lib/repository.mock';
export { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock';
export { typeRegistryMock as savedObjectsTypeRegistryMock } from './saved_objects/saved_objects_type_registry.mock';
export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock';
export { metricsServiceMock } from './metrics/metrics_service.mock';
1 change: 1 addition & 0 deletions src/dev/jest/config.js
Original file line number Diff line number Diff line change
@@ -63,6 +63,7 @@ export default {
'<rootDir>/src/dev/jest/mocks/file_mock.js',
'\\.(css|less|scss)$': '<rootDir>/src/dev/jest/mocks/style_mock.js',
'\\.ace\\.worker.js$': '<rootDir>/src/dev/jest/mocks/ace_worker_module_mock.js',
'^(!!)?file-loader!': '<rootDir>/src/dev/jest/mocks/file_mock.js',
},
setupFiles: [
'<rootDir>/src/dev/jest/setup/babel_polyfill.js',
2 changes: 0 additions & 2 deletions src/dev/precommit_hook/casing_check_config.js
Original file line number Diff line number Diff line change
@@ -159,8 +159,6 @@ export const TEMPORARILY_IGNORED_PATHS = [
'webpackShims/elasticsearch-browser.js',
'webpackShims/moment-timezone.js',
'webpackShims/ui-bootstrap.js',
'x-pack/legacy/plugins/graph/public/graphClientWorkspace.js',
'x-pack/legacy/plugins/graph/public/angular-venn-simple.js',
'x-pack/legacy/plugins/index_management/public/lib/editSettings.js',
'x-pack/legacy/plugins/license_management/public/store/reducers/licenseManagement.js',
'x-pack/legacy/plugins/monitoring/public/components/sparkline/__mocks__/plugins/xpack_main/jquery_flot.js',
44 changes: 0 additions & 44 deletions src/legacy/core_plugins/input_control_vis/index.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/legacy/core_plugins/input_control_vis/package.json

This file was deleted.

45 changes: 0 additions & 45 deletions src/legacy/core_plugins/input_control_vis/public/legacy.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -21,7 +21,9 @@ import Bluebird from 'bluebird';
import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import $ from 'jquery';
import { createVegaVisualization } from '../vega_visualization';
// Will be replaced with new path when tests are moved
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { createVegaVisualization } from '../../../../../../plugins/vis_type_vega/public/vega_visualization';
import { ImageComparator } from 'test_utils/image_comparator';

import vegaliteGraph from '!!raw-loader!./vegalite_graph.hjson';
@@ -35,24 +37,34 @@ import vegaTooltipGraph from '!!raw-loader!./vega_tooltip_test.hjson';

import vegaMapGraph from '!!raw-loader!./vega_map_test.hjson';
import vegaMapImage256 from './vega_map_image_256.png';
// Will be replaced with new path when tests are moved
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { VegaParser } from '../../../../../../plugins/vis_type_vega/public/data_model/vega_parser';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { SearchCache } from '../../../../../../plugins/vis_type_vega/public/data_model/search_cache';

import { VegaParser } from '../data_model/vega_parser';
import { SearchCache } from '../data_model/search_cache';

import { createVegaTypeDefinition } from '../vega_type';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { createVegaTypeDefinition } from '../../../../../../plugins/vis_type_vega/public/vega_type';
// TODO This is an integration test and thus requires a running platform. When moving to the new platform,
// this test has to be migrated to the newly created integration test environment.
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { npStart } from 'ui/new_platform';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { BaseVisType } from '../../../../../plugins/visualizations/public/vis_types/base_vis_type';
import { BaseVisType } from '../../../../../../plugins/visualizations/public/vis_types/base_vis_type';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { ExprVis } from '../../../../../plugins/visualizations/public/expressions/vis';
import { setInjectedVars } from '../services';
import { ExprVis } from '../../../../../../plugins/visualizations/public/expressions/vis';

import {
setInjectedVars,
setData,
setSavedObjects,
setNotifications,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../../../plugins/vis_type_vega/public/services';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { setInjectedVarFunc } from '../../../../../plugins/maps_legacy/public/kibana_services';
import { setInjectedVarFunc } from '../../../../../../plugins/maps_legacy/public/kibana_services';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { ServiceSettings } from '../../../../../plugins/maps_legacy/public/map/service_settings';
import { ServiceSettings } from '../../../../../../plugins/maps_legacy/public/map/service_settings';

const THRESHOLD = 0.1;
const PIXEL_DIFF = 30;
@@ -70,6 +82,9 @@ describe('VegaVisualizations', () => {
enableExternalUrls: true,
esShardTimeout: 10000,
});
setData(npStart.plugins.data);
setSavedObjects(npStart.core.savedObjects);
setNotifications(npStart.core.notifications);

beforeEach(ngMock.module('kibana'));
beforeEach(
@@ -111,9 +126,6 @@ describe('VegaVisualizations', () => {
timefilter: {},
},
},
__LEGACY: {
esClient: npStart.plugins.data.search.__LEGACY.esClient,
},
},
},
};
Original file line number Diff line number Diff line change
@@ -59,11 +59,7 @@ export const [getUrlTracker, setUrlTracker] = createGetterSetter<{
export const getHistory = _.once(() => createHashHistory());

export const { getRequestInspectorStats, getResponseInspectorStats, tabifyAggResponse } = search;
export {
unhashUrl,
redirectWhenMissing,
ensureDefaultIndexPattern,
} from '../../../../../plugins/kibana_utils/public';
export { unhashUrl, redirectWhenMissing } from '../../../../../plugins/kibana_utils/public';
export {
formatMsg,
formatStack,
Original file line number Diff line number Diff line change
@@ -49,7 +49,6 @@ import {
subscribeWithScope,
tabifyAggResponse,
getAngularModule,
ensureDefaultIndexPattern,
redirectWhenMissing,
} from '../../kibana_services';

@@ -118,7 +117,7 @@ app.config($routeProvider => {
savedObjects: function($route, Promise) {
const history = getHistory();
const savedSearchId = $route.current.params.id;
return ensureDefaultIndexPattern(core, data, history).then(() => {
return data.indexPatterns.ensureDefaultIndexPattern(history).then(() => {
const { appStateContainer } = getState({ history });
const { index } = appStateContainer.getState();
return Promise.props({

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -6,156 +6,7 @@
role="region"
aria-label="{{::'kbn.management.editIndexPattern.detailsAria' | i18n: { defaultMessage: 'Index pattern details' } }}"
>
<!-- Header -->
<div id="reactIndexHeader"></div>

<div class="euiSpacer euiSpacer--s"></div>
<p ng-if="::(indexPattern.timeFieldName || (indexPattern.tags && indexPattern.tags.length))">
<span ng-if="::indexPattern.timeFieldName">
<span class="euiBadge euiBadge--warning">
<span class="euiBadge__content">
<span class="euiBadge__text">
<span
i18n-id="kbn.management.editIndexPattern.timeFilterHeader"
i18n-default-message="Time Filter field name: {timeFieldName}"
i18n-values="{ timeFieldName: indexPattern.timeFieldName }">
</span>
</span>
</span>
</span>
</span>
<span ng-repeat="tag in indexPattern.tags">
<span class="euiBadge euiBadge--hollow">
<span class="euiBadge__content">
<span class="euiBadge__text">
{{tag.name}}
</span>
</span>
</span>
</span>
</p>

<div class="euiSpacer euiSpacer--m"></div>

<div class="euiText">
<p>
<span i18n-id="kbn.management.editIndexPattern.timeFilterLabel.timeFilterDetail"
i18n-default-message="This page lists every field in the {indexPatternTitle} index and the field's associated core type as recorded by Elasticsearch. To change a field type, use the Elasticsearch"
i18n-values="{ html_indexPatternTitle: '<strong>' + indexPattern.title + '</strong>' }"></span>
<a target="_blank" class="euiLink euiLink--primary" href="http://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html">
<span i18n-id="kbn.management.editIndexPattern.timeFilterLabel.mappingAPILink"
i18n-default-message="Mapping API"></span>
<i aria-hidden="true" class="fa-link fa"></i>
</a>
</p>
</div>

<div class="euiSpacer euiSpacer--m"></div>

<!-- Alerts -->
<div
ng-if="conflictFields.length"
class="kuiInfoPanel kuiInfoPanel--warning kuiVerticalRhythm"
>
<div class="kuiInfoPanelHeader">
<span class="kuiInfoPanelHeader__icon kuiIcon kuiIcon--warning fa-bolt"></span>
<span class="kuiInfoPanelHeader__title"
i18n-id="kbn.management.editIndexPattern.mappingConflictHeader"
i18n-default-message="Mapping conflict"></span>
</div>

<div class="kuiInfoPanelBody">
<div class="kuiInfoPanelBody__message">
<span i18n-id="kbn.management.editIndexPattern.mappingConflictLabel"
i18n-default-message="{conflictFieldsLength, plural, one {A field is} other {# fields are}} defined as several types (string, integer, etc) across the indices that match this pattern. You may still be able to use these conflict fields in parts of Kibana, but they will be unavailable for functions that require Kibana to know their type. Correcting this issue will require reindexing your data."
i18n-values="{ conflictFieldsLength: conflictFields.length }"></span>
</div>
</div>
</div>

<!-- Tabs -->
<div class="kuiTabs kuiVerticalRhythm">
<button
class="kuiTab"
ng-repeat="editSection in editSections"
ng-class="{ 'kuiTab-isSelected': getCurrentTab() === editSection.index }"
ng-click="setCurrentTab(editSection.index)"
data-test-subj="tab-{{ editSection.index }}"
>
{{ editSection.title }}
<span
data-test-subj="tab-count-{{ editSection.index }}"
aria-label="{{:: editSection.count + ' ' + editSection.title}}"
>
<span ng-if="editSection.count != editSection.totalCount">
({{ editSection.count }} / {{ editSection.totalCount }})
</span>
<span ng-if="editSection.count == editSection.totalCount">
({{ editSection.count }})
</span>
</span>
</button>
</div>

<!-- Field Filters -->
<form role="form" class="kuiFieldGroup kuiVerticalRhythm">
<div class="kuiFieldGroupSection kuiFieldGroupSection--wide">
<div class="kuiSearchInput">
<div class="kuiSearchInput__icon kuiIcon fa-search"></div>
<input
class="kuiSearchInput__input"
type="text"
aria-label="{{::'kbn.management.editIndexPattern.fields.filterAria' | i18n: {defaultMessage: 'Filter'} }}"
ng-model="fieldFilter"
placeholder="{{::'kbn.management.editIndexPattern.fields.filterPlaceholder' | i18n: {defaultMessage: 'Filter'} }}"
data-test-subj="indexPatternFieldFilter"
>
</div>
</div>

<div
class="kuiFieldGroupSection"
ng-if="getCurrentTab() == 'indexedFields' && indexedFieldTypes.length > 0"
>
<select
data-test-subj="indexedFieldTypeFilterDropdown"
class="kuiSelect"
ng-model="indexedFieldTypeFilter"
ng-change="changeFilter('indexedFieldTypeFilter', indexedFieldTypeFilter)"
ng-options="o for o in indexedFieldTypes"
>
<option value=""
i18n-id="kbn.management.editIndexPattern.fields.allTypesDropDown"
i18n-default-message="All field types"></option>
</select>
</div>

<div
class="kuiFieldGroupSection"
ng-if="getCurrentTab() == 'scriptedFields' && scriptedFieldLanguages.length > 0"
>
<select
data-test-subj="scriptedFieldLanguageFilterDropdown"
class="kuiSelect"
ng-model="scriptedFieldLanguageFilter"
ng-change="changeFilter('scriptedFieldLanguageFilter', scriptedFieldLanguageFilter)"
ng-options="o for o in scriptedFieldLanguages"
>
<option value=""
i18n-id="kbn.management.editIndexPattern.fields.allLangsDropDown"
i18n-default-message="All languages"></option>
</select>
</div>
</form>

<!-- Tab content -->
<div class="kuiVerticalRhythm">
<div id="reactIndexedFieldsTable"></div>

<div id="reactScriptedFieldsTable"></div>

<div id="reactSourceFiltersTable"></div>
</div>
<div id="reactEditIndexPattern"></div>
</div>
</div>
</kbn-management-app>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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.
*/

import { filter } from 'lodash';
import React, { useEffect, useState, useCallback } from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import {
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
EuiBadge,
EuiText,
EuiLink,
EuiIcon,
EuiCallOut,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { IndexPattern, IndexPatternField } from '../../../../../../../../plugins/data/public';
import {
ChromeDocTitle,
NotificationsStart,
OverlayStart,
} from '../../../../../../../../core/public';
import { IndexPatternManagementStart } from '../../../../../../../../plugins/index_pattern_management/public';
import { Tabs } from './tabs';
import { IndexHeader } from './index_header';

interface EditIndexPatternProps extends RouteComponentProps {
indexPattern: IndexPattern;
indexPatterns: IndexPattern[];
config: Record<string, any>;
services: {
notifications: NotificationsStart;
docTitle: ChromeDocTitle;
overlays: OverlayStart;
indexPatternManagement: IndexPatternManagementStart;
};
}

const mappingAPILink = i18n.translate(
'kbn.management.editIndexPattern.timeFilterLabel.mappingAPILink',
{
defaultMessage: 'Mapping API',
}
);

const mappingConflictHeader = i18n.translate(
'kbn.management.editIndexPattern.mappingConflictHeader',
{
defaultMessage: 'Mapping conflict',
}
);

const confirmMessage = i18n.translate('kbn.management.editIndexPattern.refreshLabel', {
defaultMessage: 'This action resets the popularity counter of each field.',
});

const confirmModalOptionsRefresh = {
confirmButtonText: i18n.translate('kbn.management.editIndexPattern.refreshButton', {
defaultMessage: 'Refresh',
}),
title: i18n.translate('kbn.management.editIndexPattern.refreshHeader', {
defaultMessage: 'Refresh field list?',
}),
};

const confirmModalOptionsDelete = {
confirmButtonText: i18n.translate('kbn.management.editIndexPattern.deleteButton', {
defaultMessage: 'Delete',
}),
title: i18n.translate('kbn.management.editIndexPattern.deleteHeader', {
defaultMessage: 'Delete index pattern?',
}),
};

export const EditIndexPattern = withRouter(
({ indexPattern, indexPatterns, config, services, history, location }: EditIndexPatternProps) => {
const [fields, setFields] = useState<IndexPatternField[]>(indexPattern.getNonScriptedFields());
const [conflictedFields, setConflictedFields] = useState<IndexPatternField[]>(
indexPattern.fields.filter(field => field.type === 'conflict')
);
const [defaultIndex, setDefaultIndex] = useState<string>(config.get('defaultIndex'));
const [tags, setTags] = useState<any[]>([]);

useEffect(() => {
setFields(indexPattern.getNonScriptedFields());
setConflictedFields(indexPattern.fields.filter(field => field.type === 'conflict'));
}, [indexPattern, indexPattern.fields]);

useEffect(() => {
const indexPatternTags =
services.indexPatternManagement.list.getIndexPatternTags(
indexPattern,
indexPattern.id === defaultIndex
) || [];
setTags(indexPatternTags);
}, [defaultIndex, indexPattern, services.indexPatternManagement.list]);

const setDefaultPattern = useCallback(() => {
config.set('defaultIndex', indexPattern.id);
setDefaultIndex(indexPattern.id || '');
}, [config, indexPattern.id]);

const refreshFields = () => {
services.overlays
.openConfirm(confirmMessage, confirmModalOptionsRefresh)
.then(async isConfirmed => {
if (isConfirmed) {
await indexPattern.init(true);
setFields(indexPattern.getNonScriptedFields());
}
});
};

const removePattern = () => {
function doRemove() {
if (indexPattern.id === defaultIndex) {
config.remove('defaultIndex');
const otherPatterns = filter(indexPatterns, pattern => {
return pattern.id !== indexPattern.id;
});

if (otherPatterns.length) {
config.set('defaultIndex', otherPatterns[0].id);
}
}

Promise.resolve(indexPattern.destroy()).then(function() {
history.push('/management/kibana/index_patterns');
});
}

services.overlays.openConfirm('', confirmModalOptionsDelete).then(isConfirmed => {
if (isConfirmed) {
doRemove();
}
});
};

const timeFilterHeader = i18n.translate('kbn.management.editIndexPattern.timeFilterHeader', {
defaultMessage: "Time Filter field name: '{timeFieldName}'",
values: { timeFieldName: indexPattern.timeFieldName },
});

const mappingConflictLabel = i18n.translate(
'kbn.management.editIndexPattern.mappingConflictLabel',
{
defaultMessage:
'{conflictFieldsLength, plural, one {A field is} other {# fields are}} defined as several types (string, integer, etc) across the indices that match this pattern. You may still be able to use these conflict fields in parts of Kibana, but they will be unavailable for functions that require Kibana to know their type. Correcting this issue will require reindexing your data.',
values: { conflictFieldsLength: conflictedFields.length },
}
);

services.docTitle.change(indexPattern.title);

const showTagsSection = Boolean(indexPattern.timeFieldName || (tags && tags.length > 0));

return (
<EuiFlexGroup direction="column">
<EuiFlexItem>
<IndexHeader
indexPattern={indexPattern}
setDefault={setDefaultPattern}
refreshFields={refreshFields}
deleteIndexPattern={removePattern}
defaultIndex={defaultIndex}
/>
<EuiSpacer size="s" />
{showTagsSection && (
<EuiFlexGroup wrap>
{Boolean(indexPattern.timeFieldName) && (
<EuiFlexItem grow={false}>
<EuiBadge color="warning">{timeFilterHeader}</EuiBadge>
</EuiFlexItem>
)}
{tags.map((tag: any) => (
<EuiFlexItem grow={false} key={tag.key}>
<EuiBadge color="hollow">{tag.name}</EuiBadge>
</EuiFlexItem>
))}
</EuiFlexGroup>
)}
<EuiSpacer size="m" />
<EuiText>
<p>
<FormattedMessage
id="kbn.management.editIndexPattern.timeFilterLabel.timeFilterDetail"
defaultMessage="This page lists every field in the {indexPatternTitle} index and the field's associated core type as recorded by Elasticsearch. To change a field type, use the Elasticsearch"
values={{ indexPatternTitle: <strong>{indexPattern.title}</strong> }}
/>{' '}
<EuiLink
href="http://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html"
target="_blank"
>
{mappingAPILink}
<EuiIcon type="link" />
</EuiLink>
</p>
</EuiText>
{conflictedFields.length > 0 && (
<EuiCallOut title={mappingConflictHeader} color="warning" iconType="alert">
<p>{mappingConflictLabel}</p>
</EuiCallOut>
)}
</EuiFlexItem>
<EuiFlexItem>
<Tabs
indexPattern={indexPattern}
fields={fields}
config={config}
services={{
indexPatternManagement: services.indexPatternManagement,
}}
history={history}
location={location}
/>
</EuiFlexItem>
</EuiFlexGroup>
);
}
);
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ import {
} from '../../../../../../../../plugins/kibana_utils/public';

interface IEditIndexPatternState {
tab: string; // TODO: type those 3 tabs with enum, when edit_index_pattern.js migrated to ts
tab: string;
}

/**
@@ -38,7 +38,6 @@ export function createEditIndexPatternPageStateContainer({
defaultTab: string;
useHashedUrl: boolean;
}) {
// until angular is used as shell - use hash history
const history = createHashHistory();
// query param to store app state at
const stateStorageKey = '_a';
@@ -78,12 +77,10 @@ export function createEditIndexPatternPageStateContainer({
// makes sure initial url is the same as initial state (this is not really required)
kbnUrlStateStorage.set(stateStorageKey, stateContainer.getState(), { replace: true });

// expose api needed for Controller
return {
startSyncingState: start,
stopSyncingState: stop,
setCurrentTab: (newTab: string) => stateContainer.transitions.setTab(newTab),
getCurrentTab: () => stateContainer.selectors.tab(),
state$: stateContainer.state$,
};
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -17,4 +17,159 @@
* under the License.
*/

import './edit_index_pattern';
import React from 'react';
import { HashRouter } from 'react-router-dom';
import { render, unmountComponentAtNode } from 'react-dom';
import { RegistryFieldFormatEditorsProvider } from 'ui/registry/field_format_editors';
import uiRoutes from 'ui/routes';
import { uiModules } from 'ui/modules';
import { I18nContext } from 'ui/i18n';
import { npStart } from 'ui/new_platform';
import template from './edit_index_pattern.html';
import createEditFieldtemplate from './create_edit_field.html';
import {
getEditBreadcrumbs,
getEditFieldBreadcrumbs,
getCreateFieldBreadcrumbs,
} from '../breadcrumbs';
import { EditIndexPattern } from './edit_index_pattern';
import { CreateEditField } from './create_edit_field';

const REACT_EDIT_INDEX_PATTERN_DOM_ELEMENT_ID = 'reactEditIndexPattern';

function destroyEditIndexPattern() {
const node = document.getElementById(REACT_EDIT_INDEX_PATTERN_DOM_ELEMENT_ID);
node && unmountComponentAtNode(node);
}

function renderEditIndexPattern($scope, config, $route) {
$scope.$$postDigest(() => {
const node = document.getElementById(REACT_EDIT_INDEX_PATTERN_DOM_ELEMENT_ID);
if (!node) {
return;
}

render(
<HashRouter>
<I18nContext>
<EditIndexPattern
indexPattern={$route.current.locals.indexPattern}
indexPatterns={$route.current.locals.indexPatterns}
config={config}
services={{
notifications: npStart.core.notifications,
docTitle: npStart.core.chrome.docTitle,
overlays: npStart.core.overlays,
indexPatternManagement: npStart.plugins.indexPatternManagement,
}}
/>
</I18nContext>
</HashRouter>,
node
);
});
}

uiRoutes.when('/management/kibana/index_patterns/:indexPatternId', {
template,
k7Breadcrumbs: getEditBreadcrumbs,
resolve: {
indexPattern: function($route, Promise, redirectWhenMissing) {
const { indexPatterns } = npStart.plugins.data;
return Promise.resolve(indexPatterns.get($route.current.params.indexPatternId)).catch(
redirectWhenMissing('/management/kibana/index_patterns')
);
},
},
});

uiModules
.get('apps/management')
.controller('managementIndexPatternsEdit', function($scope, $route, config) {
$scope.$on('$destroy', () => {
destroyEditIndexPattern();
});

renderEditIndexPattern($scope, config, $route);
});

// routes for create edit field. Will be removed after migartion all component to react.
const REACT_FIELD_EDITOR_ID = 'reactFieldEditor';
const renderCreateEditField = ($scope, $route, getConfig, $http, fieldFormatEditors) => {
$scope.$$postDigest(() => {
const node = document.getElementById(REACT_FIELD_EDITOR_ID);
if (!node) {
return;
}

render(
<HashRouter>
<I18nContext>
<CreateEditField
indexPattern={$route.current.locals.indexPattern}
mode={$route.current.mode}
fieldName={$route.current.params.fieldName}
fieldFormatEditors={fieldFormatEditors}
getConfig={getConfig}
services={{
http: $http,
notifications: npStart.core.notifications,
docTitle: npStart.core.chrome.docTitle,
}}
/>
</I18nContext>
</HashRouter>,
node
);
});
};

const destroyCreateEditField = () => {
const node = document.getElementById(REACT_FIELD_EDITOR_ID);
node && unmountComponentAtNode(node);
};

uiRoutes
.when('/management/kibana/index_patterns/:indexPatternId/field/:fieldName*', {
mode: 'edit',
k7Breadcrumbs: getEditFieldBreadcrumbs,
})
.when('/management/kibana/index_patterns/:indexPatternId/create-field/', {
mode: 'create',
k7Breadcrumbs: getCreateFieldBreadcrumbs,
})
.defaults(/management\/kibana\/index_patterns\/[^\/]+\/(field|create-field)(\/|$)/, {
template: createEditFieldtemplate,
mapBreadcrumbs($route, breadcrumbs) {
const { indexPattern } = $route.current.locals;
return breadcrumbs.map(crumb => {
if (crumb.id !== indexPattern.id) {
return crumb;
}

return {
...crumb,
display: indexPattern.title,
};
});
},
resolve: {
indexPattern: function($route, Promise, redirectWhenMissing) {
const { indexPatterns } = npStart.plugins.data;
return Promise.resolve(indexPatterns.get($route.current.params.indexPatternId)).catch(
redirectWhenMissing('/management/kibana/index_patterns')
);
},
},
controllerAs: 'fieldSettings',
controller: function FieldEditorPageController($scope, $route, $http, Private, config) {
const getConfig = (...args) => config.get(...args);
const fieldFormatEditors = Private(RegistryFieldFormatEditorsProvider);

renderCreateEditField($scope, $route, getConfig, $http, fieldFormatEditors);

$scope.$on('$destroy', () => {
destroyCreateEditField();
});
},
});
Original file line number Diff line number Diff line change
@@ -92,7 +92,7 @@ export function IndexHeader({
<EuiButtonIcon
color="text"
onClick={setDefault}
iconType="starFilledSpace"
iconType="starFilled"
aria-label={setDefaultAriaLabel}
data-test-subj="setDefaultIndexPatternButton"
/>
Original file line number Diff line number Diff line change
@@ -19,7 +19,11 @@

import React, { Component } from 'react';
import { createSelector } from 'reselect';
import { IndexPatternField, IIndexPattern } from '../../../../../../../../../plugins/data/public';
import {
IndexPatternField,
IIndexPattern,
IFieldType,
} from '../../../../../../../../../plugins/data/public';
import { Table } from './components/table';
import { getFieldFormat } from './lib';
import { IndexedFieldItem } from './types';
@@ -31,7 +35,7 @@ interface IndexedFieldsTableProps {
indexedFieldTypeFilter?: string;
helpers: {
redirectToRoute: (obj: any) => void;
getFieldInfo: (indexPattern: IIndexPattern, field: string) => string[];
getFieldInfo: (indexPattern: IIndexPattern, field: IFieldType) => string[];
};
fieldWildcardMatcher: (filters: any[]) => (val: any) => boolean;
}
@@ -76,7 +80,7 @@ export class IndexedFieldsTable extends Component<
indexPattern: field.indexPattern,
format: getFieldFormat(indexPattern, field.name),
excluded: fieldWildcardMatch ? fieldWildcardMatch(field.name) : false,
info: helpers.getFieldInfo && helpers.getFieldInfo(indexPattern, field.name),
info: helpers.getFieldInfo && helpers.getFieldInfo(indexPattern, field),
};
})) ||
[]

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ interface ScriptedFieldsTableProps {
scriptedFieldLanguageFilter?: string;
helpers: {
redirectToRoute: Function;
getRouteHref: Function;
getRouteHref?: Function;
};
onRemoveField?: () => void;
}
@@ -136,14 +136,19 @@ export class ScriptedFieldsTable extends Component<
};

render() {
const { helpers, indexPattern } = this.props;
const { indexPattern } = this.props;
const { fieldToDelete, deprecatedLangsInUse } = this.state;

const items = this.getFilteredItems();

return (
<>
<Header addScriptedFieldUrl={helpers.getRouteHref(indexPattern, 'addField')} />
<Header
addScriptedFieldUrl={`${window.location.origin +
window.location.pathname}#/management/kibana/index_patterns/${
indexPattern.id
}/create-field/`}
/>

<CallOuts
deprecatedLangsInUse={deprecatedLangsInUse}
Original file line number Diff line number Diff line change
@@ -17,9 +17,4 @@
* under the License.
*/

import { PluginInitializerContext } from '../../../../core/public';
import { VegaPlugin as Plugin } from './plugin';

export function plugin(initializerContext: PluginInitializerContext) {
return new Plugin(initializerContext);
}
export { Tabs } from './tabs';
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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.
*/

import React, { useState, useCallback, useEffect, Fragment, useMemo } from 'react';
import { RouteComponentProps } from 'react-router-dom';
import {
EuiFlexGroup,
EuiFlexItem,
EuiTabbedContent,
EuiTabbedContentTab,
EuiSpacer,
EuiFieldSearch,
EuiSelect,
EuiSelectOption,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { fieldWildcardMatcher } from '../../../../../../../../../plugins/kibana_utils/public';
import { IndexPatternManagementStart } from '../../../../../../../../../plugins/index_pattern_management/public';
import { IndexPattern, IndexPatternField } from '../../../../../../../../../plugins/data/public';
import { createEditIndexPatternPageStateContainer } from '../edit_index_pattern_state_container';
import { TAB_INDEXED_FIELDS, TAB_SCRIPTED_FIELDS, TAB_SOURCE_FILTERS } from '../constants';
import { SourceFiltersTable } from '../source_filters_table';
import { IndexedFieldsTable } from '../indexed_fields_table';
import { ScriptedFieldsTable } from '../scripted_fields_table';
import { getTabs, getPath, convertToEuiSelectOption } from './utils';

interface TabsProps extends Pick<RouteComponentProps, 'history' | 'location'> {
indexPattern: IndexPattern;
config: Record<string, any>;
fields: IndexPatternField[];
services: {
indexPatternManagement: IndexPatternManagementStart;
};
}

const filterAriaLabel = i18n.translate('kbn.management.editIndexPattern.fields.filterAria', {
defaultMessage: 'Filter',
});

const filterPlaceholder = i18n.translate(
'kbn.management.editIndexPattern.fields.filterPlaceholder',
{
defaultMessage: 'Filter',
}
);

export function Tabs({ config, indexPattern, fields, services, history, location }: TabsProps) {
const [fieldFilter, setFieldFilter] = useState<string>('');
const [indexedFieldTypeFilter, setIndexedFieldTypeFilter] = useState<string>('');
const [scriptedFieldLanguageFilter, setScriptedFieldLanguageFilter] = useState<string>('');
const [indexedFieldTypes, setIndexedFieldType] = useState<EuiSelectOption[]>([]);
const [scriptedFieldLanguages, setScriptedFieldLanguages] = useState<EuiSelectOption[]>([]);
const [syncingStateFunc, setSyncingStateFunc] = useState<any>({
getCurrentTab: () => TAB_INDEXED_FIELDS,
});

const refreshFilters = useCallback(() => {
const tempIndexedFieldTypes: string[] = [];
const tempScriptedFieldLanguages: string[] = [];
indexPattern.fields.forEach(field => {
if (field.scripted) {
if (field.lang) {
tempScriptedFieldLanguages.push(field.lang);
}
} else {
tempIndexedFieldTypes.push(field.type);
}
});

setIndexedFieldType(convertToEuiSelectOption(tempIndexedFieldTypes, 'indexedFiledTypes'));
setScriptedFieldLanguages(
convertToEuiSelectOption(tempScriptedFieldLanguages, 'scriptedFieldLanguages')
);
}, [indexPattern]);

useEffect(() => {
refreshFilters();
}, [indexPattern, indexPattern.fields, refreshFilters]);

const fieldWildcardMatcherDecorated = useCallback(
(filters: string[]) => fieldWildcardMatcher(filters, config.get('metaFields')),
[config]
);

const getFilterSection = useCallback(
(type: string) => {
return (
<EuiFlexGroup>
<EuiFlexItem grow={true}>
<EuiFieldSearch
placeholder={filterPlaceholder}
value={fieldFilter}
onChange={e => setFieldFilter(e.target.value)}
data-test-subj="indexPatternFieldFilter"
aria-label={filterAriaLabel}
/>
</EuiFlexItem>
{type === TAB_INDEXED_FIELDS && indexedFieldTypes.length > 0 && (
<EuiFlexItem grow={false}>
<EuiSelect
options={indexedFieldTypes}
value={indexedFieldTypeFilter}
onChange={e => setIndexedFieldTypeFilter(e.target.value)}
data-test-subj="indexedFieldTypeFilterDropdown"
/>
</EuiFlexItem>
)}
{type === TAB_SCRIPTED_FIELDS && scriptedFieldLanguages.length > 0 && (
<EuiFlexItem grow={false}>
<EuiSelect
options={scriptedFieldLanguages}
value={scriptedFieldLanguageFilter}
onChange={e => setScriptedFieldLanguageFilter(e.target.value)}
data-test-subj="scriptedFieldLanguageFilterDropdown"
/>
</EuiFlexItem>
)}
</EuiFlexGroup>
);
},
[
fieldFilter,
indexedFieldTypeFilter,
indexedFieldTypes,
scriptedFieldLanguageFilter,
scriptedFieldLanguages,
]
);

const getContent = useCallback(
(type: string) => {
switch (type) {
case TAB_INDEXED_FIELDS:
return (
<Fragment>
<EuiSpacer size="m" />
{getFilterSection(type)}
<EuiSpacer size="m" />
<IndexedFieldsTable
fields={fields}
indexPattern={indexPattern}
fieldFilter={fieldFilter}
fieldWildcardMatcher={fieldWildcardMatcherDecorated}
indexedFieldTypeFilter={indexedFieldTypeFilter}
helpers={{
redirectToRoute: (field: IndexPatternField) => {
history.push(getPath(field));
},
getFieldInfo: services.indexPatternManagement.list.getFieldInfo,
}}
/>
</Fragment>
);
case TAB_SCRIPTED_FIELDS:
return (
<Fragment>
<EuiSpacer size="m" />
{getFilterSection(type)}
<EuiSpacer size="m" />
<ScriptedFieldsTable
indexPattern={indexPattern}
fieldFilter={fieldFilter}
scriptedFieldLanguageFilter={scriptedFieldLanguageFilter}
helpers={{
redirectToRoute: (field: IndexPatternField) => {
history.push(getPath(field));
},
}}
onRemoveField={refreshFilters}
/>
</Fragment>
);
case TAB_SOURCE_FILTERS:
return (
<Fragment>
<EuiSpacer size="m" />
{getFilterSection(type)}
<EuiSpacer size="m" />
<SourceFiltersTable
indexPattern={indexPattern}
filterFilter={fieldFilter}
fieldWildcardMatcher={fieldWildcardMatcherDecorated}
onAddOrRemoveFilter={refreshFilters}
/>
</Fragment>
);
}
},
[
fieldFilter,
fieldWildcardMatcherDecorated,
fields,
getFilterSection,
history,
indexPattern,
indexedFieldTypeFilter,
refreshFilters,
scriptedFieldLanguageFilter,
services.indexPatternManagement.list.getFieldInfo,
]
);

const euiTabs: EuiTabbedContentTab[] = useMemo(
() =>
getTabs(indexPattern, fieldFilter, services.indexPatternManagement.list).map(
(tab: Pick<EuiTabbedContentTab, 'name' | 'id'>) => {
return {
...tab,
content: getContent(tab.id),
};
}
),
[fieldFilter, getContent, indexPattern, services.indexPatternManagement.list]
);

const [selectedTabId, setSelectedTabId] = useState(euiTabs[0].id);

useEffect(() => {
const {
startSyncingState,
stopSyncingState,
setCurrentTab,
getCurrentTab,
} = createEditIndexPatternPageStateContainer({
useHashedUrl: config.get('state:storeInSessionStorage'),
defaultTab: TAB_INDEXED_FIELDS,
});

startSyncingState();
setSyncingStateFunc({
setCurrentTab,
getCurrentTab,
});
setSelectedTabId(getCurrentTab());

return () => {
stopSyncingState();
};
}, [config]);

return (
<EuiTabbedContent
tabs={euiTabs}
selectedTab={euiTabs.find(tab => tab.id === selectedTabId)}
onTabClick={tab => {
setSelectedTabId(tab.id);
syncingStateFunc.setCurrentTab(tab.id);
}}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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.
*/

import { Dictionary, countBy, defaults, unique } from 'lodash';
import { i18n } from '@kbn/i18n';
import { IndexPattern, IndexPatternField } from '../../../../../../../../../plugins/data/public';
import { IndexPatternManagementStart } from '../../../../../../../../../plugins/index_pattern_management/public';
import { TAB_INDEXED_FIELDS, TAB_SCRIPTED_FIELDS, TAB_SOURCE_FILTERS } from '../constants';

function filterByName(items: IndexPatternField[], filter: string) {
const lowercaseFilter = (filter || '').toLowerCase();
return items.filter(item => item.name.toLowerCase().includes(lowercaseFilter));
}

function getCounts(
fields: IndexPatternField[],
sourceFilters: {
excludes: string[];
},
fieldFilter = ''
) {
const fieldCount = countBy(filterByName(fields, fieldFilter), function(field) {
return field.scripted ? 'scripted' : 'indexed';
});

defaults(fieldCount, {
indexed: 0,
scripted: 0,
sourceFilters: sourceFilters.excludes
? sourceFilters.excludes.filter(value =>
value.toLowerCase().includes(fieldFilter.toLowerCase())
).length
: 0,
});

return fieldCount;
}

function getTitle(type: string, filteredCount: Dictionary<number>, totalCount: Dictionary<number>) {
let title = '';
switch (type) {
case 'indexed':
title = i18n.translate('kbn.management.editIndexPattern.tabs.fieldsHeader', {
defaultMessage: 'Fields',
});
break;
case 'scripted':
title = i18n.translate('kbn.management.editIndexPattern.tabs.scriptedHeader', {
defaultMessage: 'Scripted fields',
});
break;
case 'sourceFilters':
title = i18n.translate('kbn.management.editIndexPattern.tabs.sourceHeader', {
defaultMessage: 'Source filters',
});
break;
}
const count = ` (${
filteredCount[type] === totalCount[type]
? filteredCount[type]
: filteredCount[type] + ' / ' + totalCount[type]
})`;
return title + count;
}

export function getTabs(
indexPattern: IndexPattern,
fieldFilter: string,
indexPatternListProvider: IndexPatternManagementStart['list']
) {
const totalCount = getCounts(indexPattern.fields, indexPattern.getSourceFiltering());
const filteredCount = getCounts(
indexPattern.fields,
indexPattern.getSourceFiltering(),
fieldFilter
);

const tabs = [];

tabs.push({
name: getTitle('indexed', filteredCount, totalCount),
id: TAB_INDEXED_FIELDS,
});

if (indexPatternListProvider.areScriptedFieldsEnabled(indexPattern)) {
tabs.push({
name: getTitle('scripted', filteredCount, totalCount),
id: TAB_SCRIPTED_FIELDS,
});
}

tabs.push({
name: getTitle('sourceFilters', filteredCount, totalCount),
id: TAB_SOURCE_FILTERS,
});

return tabs;
}

export function getPath(field: IndexPatternField) {
return `/management/kibana/index_patterns/${field.indexPattern?.id}/field/${field.name}`;
}

const allTypesDropDown = i18n.translate('kbn.management.editIndexPattern.fields.allTypesDropDown', {
defaultMessage: 'All field types',
});

const allLangsDropDown = i18n.translate('kbn.management.editIndexPattern.fields.allLangsDropDown', {
defaultMessage: 'All languages',
});

export function convertToEuiSelectOption(options: string[], type: string) {
const euiOptions =
options.length > 0
? [
{
value: '',
text: type === 'scriptedFieldLanguages' ? allLangsDropDown : allTypesDropDown,
},
]
: [];
return euiOptions.concat(
unique(options).map(option => {
return {
value: option,
text: option,
};
})
);
}
13 changes: 13 additions & 0 deletions src/legacy/core_plugins/tests_bundle/index.js
Original file line number Diff line number Diff line change
@@ -148,6 +148,19 @@ export default kibana => {
.type('text/css');
},
});

// Sets global variables normally set by the bootstrap.js script
kbnServer.server.route({
path: '/test_bundle/karma/globals.js',
method: 'GET',
async handler(req, h) {
const basePath = config.get('server.basePath');

const file = `window.__kbnPublicPath__ = { 'kbn-ui-shared-deps': "${basePath}/bundles/kbn-ui-shared-deps/" };`;

return h.response(file).header('content-type', 'application/json');
},
});
},

__globalImportAliases__: {
55 changes: 0 additions & 55 deletions src/legacy/core_plugins/vis_type_vega/index.ts

This file was deleted.

6 changes: 0 additions & 6 deletions src/legacy/core_plugins/vis_type_vega/package.json

This file was deleted.

2 changes: 0 additions & 2 deletions src/legacy/ui/public/new_platform/new_platform.ts
Original file line number Diff line number Diff line change
@@ -59,7 +59,6 @@ import {
NavigationPublicPluginSetup,
NavigationPublicPluginStart,
} from '../../../../plugins/navigation/public';
import { VisTypeVegaSetup } from '../../../../plugins/vis_type_vega/public';
import { DiscoverSetup, DiscoverStart } from '../../../../plugins/discover/public';
import {
SavedObjectsManagementPluginSetup,
@@ -88,7 +87,6 @@ export interface PluginsSetup {
usageCollection: UsageCollectionSetup;
advancedSettings: AdvancedSettingsSetup;
management: ManagementSetup;
visTypeVega: VisTypeVegaSetup;
discover: DiscoverSetup;
visualizations: VisualizationsSetup;
telemetry?: TelemetryPluginSetup;
1 change: 1 addition & 0 deletions src/legacy/ui/ui_exports/ui_export_defaults.js
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ export const UI_EXPORT_DEFAULTS = {
webpackNoParseRules: [
/node_modules[\/\\](angular|elasticsearch-browser)[\/\\]/,
/node_modules[\/\\](mocha|moment)[\/\\]/,
/node_modules[\/\\]vega-lib[\/\\]build[\/\\]vega\.js$/,
],

webpackAliases: {
1 change: 1 addition & 0 deletions src/legacy/ui/ui_render/bootstrap/template.js.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var kbnCsp = JSON.parse(document.querySelector('kbn-csp').getAttribute('data'));
window.__kbnStrictCsp__ = kbnCsp.strictCsp;
window.__kbnDarkMode__ = {{darkMode}};
window.__kbnPublicPath__ = {{publicPathMap}};

if (window.__kbnStrictCsp__ && window.__kbnCspNotEnforced__) {
var legacyBrowserError = document.getElementById('kbn_legacy_browser_error');
14 changes: 14 additions & 0 deletions src/legacy/ui/ui_render/ui_render_mixin.js
Original file line number Diff line number Diff line change
@@ -153,11 +153,25 @@ export function uiRenderMixin(kbnServer, server, config) {
`${regularBundlePath}/plugin/kibanaReact/kibanaReact.plugin.js`,
];

const uiPluginIds = [...kbnServer.newPlatform.__internals.uiPlugins.public.keys()];

// These paths should align with the bundle routes configured in
// src/optimize/bundles_route/bundles_route.js
const publicPathMap = JSON.stringify({
core: `${regularBundlePath}/core/`,
'kbn-ui-shared-deps': `${regularBundlePath}/kbn-ui-shared-deps/`,
...uiPluginIds.reduce(
(acc, pluginId) => ({ ...acc, [pluginId]: `${regularBundlePath}/plugin/${pluginId}/` }),
{}
),
});

const bootstrap = new AppBootstrap({
templateData: {
darkMode,
jsDependencyPaths,
styleSheetPaths,
publicPathMap,
entryBundlePath: isCore
? `${regularBundlePath}/core/core.entry.js`
: `${regularBundlePath}/${app.getId()}.bundle.js`,
79 changes: 47 additions & 32 deletions src/optimize/bundles_route/bundles_route.js
Original file line number Diff line number Diff line change
@@ -72,43 +72,57 @@ export function createBundlesRoute({
}

return [
buildRouteForBundles(
`${basePublicPath}/bundles/kbn-ui-shared-deps/`,
'/bundles/kbn-ui-shared-deps/',
UiSharedDeps.distDir,
fileHashCache
),
buildRouteForBundles({
publicPath: `${basePublicPath}/bundles/kbn-ui-shared-deps/`,
routePath: '/bundles/kbn-ui-shared-deps/',
bundlesPath: UiSharedDeps.distDir,
fileHashCache,
replacePublicPath: false,
}),
...npUiPluginPublicDirs.map(({ id, path }) =>
buildRouteForBundles(
`${basePublicPath}/bundles/plugin/${id}/`,
`/bundles/plugin/${id}/`,
path,
fileHashCache
)
),
buildRouteForBundles(
`${basePublicPath}/bundles/core/`,
`/bundles/core/`,
fromRoot(join('src', 'core', 'target', 'public')),
fileHashCache
),
buildRouteForBundles(
`${basePublicPath}/bundles/`,
'/bundles/',
regularBundlesPath,
fileHashCache
buildRouteForBundles({
publicPath: `${basePublicPath}/bundles/plugin/${id}/`,
routePath: `/bundles/plugin/${id}/`,
bundlesPath: path,
fileHashCache,
replacePublicPath: false,
})
),
buildRouteForBundles(
`${basePublicPath}/built_assets/dlls/`,
'/built_assets/dlls/',
dllBundlesPath,
fileHashCache
),
buildRouteForBundles(`${basePublicPath}/`, '/built_assets/css/', builtCssPath, fileHashCache),
buildRouteForBundles({
publicPath: `${basePublicPath}/bundles/core/`,
routePath: `/bundles/core/`,
bundlesPath: fromRoot(join('src', 'core', 'target', 'public')),
fileHashCache,
replacePublicPath: false,
}),
buildRouteForBundles({
publicPath: `${basePublicPath}/bundles/`,
routePath: '/bundles/',
bundlesPath: regularBundlesPath,
fileHashCache,
}),
buildRouteForBundles({
publicPath: `${basePublicPath}/built_assets/dlls/`,
routePath: '/built_assets/dlls/',
bundlesPath: dllBundlesPath,
fileHashCache,
}),
buildRouteForBundles({
publicPath: `${basePublicPath}/`,
routePath: '/built_assets/css/',
bundlesPath: builtCssPath,
fileHashCache,
}),
];
}

function buildRouteForBundles(publicPath, routePath, bundlesPath, fileHashCache) {
function buildRouteForBundles({
publicPath,
routePath,
bundlesPath,
fileHashCache,
replacePublicPath = true,
}) {
return {
method: 'GET',
path: `${routePath}{path*}`,
@@ -129,6 +143,7 @@ function buildRouteForBundles(publicPath, routePath, bundlesPath, fileHashCache)
bundlesPath,
fileHashCache,
publicPath,
replacePublicPath,
});
},
},
9 changes: 6 additions & 3 deletions src/optimize/bundles_route/dynamic_asset_response.js
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ import { replacePlaceholder } from '../public_path_placeholder';
* @property {LruCache} options.fileHashCache
*/
export async function createDynamicAssetResponse(options) {
const { request, h, bundlesPath, publicPath, fileHashCache } = options;
const { request, h, bundlesPath, publicPath, fileHashCache, replacePublicPath } = options;

let fd;
try {
@@ -78,11 +78,14 @@ export async function createDynamicAssetResponse(options) {
});
fd = null; // read stream is now responsible for fd

const content = replacePublicPath ? replacePlaceholder(read, publicPath) : read;
const etag = replacePublicPath ? `${hash}-${publicPath}` : hash;

return h
.response(replacePlaceholder(read, publicPath))
.response(content)
.takeover()
.code(200)
.etag(`${hash}-${publicPath}`)
.etag(etag)
.header('cache-control', 'must-revalidate')
.type(request.server.mime.path(path).type);
} catch (error) {
9 changes: 5 additions & 4 deletions src/plugins/dashboard/public/application/legacy_app.js
Original file line number Diff line number Diff line change
@@ -28,7 +28,6 @@ import { initDashboardAppDirective } from './dashboard_app';
import { createDashboardEditUrl, DashboardConstants } from '../dashboard_constants';
import {
createKbnUrlStateStorage,
ensureDefaultIndexPattern,
redirectWhenMissing,
InvalidJSONProperty,
SavedObjectNotFound,
@@ -138,7 +137,7 @@ export function initDashboardApp(app, deps) {
},
resolve: {
dash: function($route, history) {
return ensureDefaultIndexPattern(deps.core, deps.data, history).then(() => {
return deps.data.indexPatterns.ensureDefaultIndexPattern(history).then(() => {
const savedObjectsClient = deps.savedObjectsClient;
const title = $route.current.params.title;
if (title) {
@@ -173,7 +172,8 @@ export function initDashboardApp(app, deps) {
requireUICapability: 'dashboard.createNew',
resolve: {
dash: history =>
ensureDefaultIndexPattern(deps.core, deps.data, history)
deps.data.indexPatterns
.ensureDefaultIndexPattern(history)
.then(() => deps.savedDashboards.get())
.catch(
redirectWhenMissing({
@@ -194,7 +194,8 @@ export function initDashboardApp(app, deps) {
dash: function($route, history) {
const id = $route.current.params.id;

return ensureDefaultIndexPattern(deps.core, deps.data, history)
return deps.data.indexPatterns
.ensureDefaultIndexPattern(history)
.then(() => deps.savedDashboards.get(id))
.then(savedDashboard => {
deps.chrome.recentlyAccessed.add(
27 changes: 27 additions & 0 deletions src/plugins/data/common/es_query/kuery/ast/ast.test.ts
Original file line number Diff line number Diff line change
@@ -278,6 +278,33 @@ describe('kuery AST API', () => {
expect(fromLiteralExpression('true')).toEqual(booleanTrueLiteral);
expect(fromLiteralExpression('false')).toEqual(booleanFalseLiteral);
expect(fromLiteralExpression('42')).toEqual(numberLiteral);

expect(fromLiteralExpression('.3').value).toEqual(0.3);
expect(fromLiteralExpression('.36').value).toEqual(0.36);
expect(fromLiteralExpression('.00001').value).toEqual(0.00001);
expect(fromLiteralExpression('3').value).toEqual(3);
expect(fromLiteralExpression('-4').value).toEqual(-4);
expect(fromLiteralExpression('0').value).toEqual(0);
expect(fromLiteralExpression('0.0').value).toEqual(0);
expect(fromLiteralExpression('2.0').value).toEqual(2.0);
expect(fromLiteralExpression('0.8').value).toEqual(0.8);
expect(fromLiteralExpression('790.9').value).toEqual(790.9);
expect(fromLiteralExpression('0.0001').value).toEqual(0.0001);
expect(fromLiteralExpression('96565646732345').value).toEqual(96565646732345);

expect(fromLiteralExpression('..4').value).toEqual('..4');
expect(fromLiteralExpression('.3text').value).toEqual('.3text');
expect(fromLiteralExpression('text').value).toEqual('text');
expect(fromLiteralExpression('.').value).toEqual('.');
expect(fromLiteralExpression('-').value).toEqual('-');
expect(fromLiteralExpression('001').value).toEqual('001');
expect(fromLiteralExpression('00.2').value).toEqual('00.2');
expect(fromLiteralExpression('0.0.1').value).toEqual('0.0.1');
expect(fromLiteralExpression('3.').value).toEqual('3.');
expect(fromLiteralExpression('--4').value).toEqual('--4');
expect(fromLiteralExpression('-.4').value).toEqual('-.4');
expect(fromLiteralExpression('-0').value).toEqual('-0');
expect(fromLiteralExpression('00949').value).toEqual('00949');
});

test('should allow escaping of special characters with a backslash', () => {
5 changes: 2 additions & 3 deletions src/plugins/data/common/es_query/kuery/ast/kuery.peg
Original file line number Diff line number Diff line change
@@ -247,9 +247,8 @@ UnquotedLiteral
if (sequence === 'true') return buildLiteralNode(true);
if (sequence === 'false') return buildLiteralNode(false);
if (chars.includes(wildcardSymbol)) return buildWildcardNode(sequence);
const number = Number(sequence);
const value = isNaN(number) ? sequence : number;
return buildLiteralNode(value);
const isNumberPattern = /^(-?[1-9]+\d*([.]\d+)?)$|^(-?0[.]\d*[1-9]+)$|^0$|^0.0$|^[.]\d{1,}$/
return buildLiteralNode(isNumberPattern.test(sequence) ? Number(sequence) : sequence);
}

UnquotedCharacter
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
* under the License.
*/

import { IFieldFormatType } from '../types';
import { FieldFormatInstanceType } from '../types';

import {
BoolFormat,
@@ -36,7 +36,7 @@ import {
UrlFormat,
} from '../converters';

export const baseFormatters: IFieldFormatType[] = [
export const baseFormatters: FieldFormatInstanceType[] = [
BoolFormat,
BytesFormat,
ColorFormat,
4 changes: 2 additions & 2 deletions src/plugins/data/common/field_formats/converters/custom.ts
Original file line number Diff line number Diff line change
@@ -18,9 +18,9 @@
*/

import { FieldFormat } from '../field_format';
import { TextContextTypeConvert, FIELD_FORMAT_IDS, IFieldFormatType } from '../types';
import { TextContextTypeConvert, FIELD_FORMAT_IDS, FieldFormatInstanceType } from '../types';

export const createCustomFieldFormat = (convert: TextContextTypeConvert): IFieldFormatType =>
export const createCustomFieldFormat = (convert: TextContextTypeConvert): FieldFormatInstanceType =>
class CustomFieldFormat extends FieldFormat {
static id = FIELD_FORMAT_IDS.CUSTOM;

4 changes: 2 additions & 2 deletions src/plugins/data/common/field_formats/field_format.ts
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ import { createCustomFieldFormat } from './converters/custom';
import {
FieldFormatsGetConfigFn,
FieldFormatsContentType,
IFieldFormatType,
FieldFormatInstanceType,
FieldFormatConvert,
FieldFormatConvertFunction,
HtmlContextTypeOptions,
@@ -199,7 +199,7 @@ export abstract class FieldFormat {
};
}

static from(convertFn: FieldFormatConvertFunction): IFieldFormatType {
static from(convertFn: FieldFormatConvertFunction): FieldFormatInstanceType {
return createCustomFieldFormat(convertFn);
}

Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@
*/
import { FieldFormatsRegistry } from './field_formats_registry';
import { BoolFormat, PercentFormat, StringFormat } from './converters';
import { FieldFormatsGetConfigFn, IFieldFormatType } from './types';
import { FieldFormatsGetConfigFn, FieldFormatInstanceType } from './types';
import { KBN_FIELD_TYPES } from '../../common';

const getValueOfPrivateField = (instance: any, field: string) => instance[field];
@@ -75,10 +75,10 @@ describe('FieldFormatsRegistry', () => {
test('should register field formats', () => {
fieldFormatsRegistry.register([StringFormat, BoolFormat]);

const registeredFieldFormatters: Map<string, IFieldFormatType> = getValueOfPrivateField(
fieldFormatsRegistry,
'fieldFormats'
);
const registeredFieldFormatters: Map<
string,
FieldFormatInstanceType
> = getValueOfPrivateField(fieldFormatsRegistry, 'fieldFormats');

expect(registeredFieldFormatters.size).toBe(2);

40 changes: 21 additions & 19 deletions src/plugins/data/common/field_formats/field_formats_registry.ts
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ import {
FieldFormatsGetConfigFn,
FieldFormatConfig,
FIELD_FORMAT_IDS,
IFieldFormatType,
FieldFormatInstanceType,
FieldFormatId,
IFieldFormatMetaParams,
IFieldFormat,
@@ -35,7 +35,7 @@ import { SerializedFieldFormat } from '../../../expressions/common/types';
import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../types';

export class FieldFormatsRegistry {
protected fieldFormats: Map<FieldFormatId, IFieldFormatType> = new Map();
protected fieldFormats: Map<FieldFormatId, FieldFormatInstanceType> = new Map();
protected defaultMap: Record<string, FieldFormatConfig> = {};
protected metaParamsOptions: Record<string, any> = {};
protected getConfig?: FieldFormatsGetConfigFn;
@@ -47,7 +47,7 @@ export class FieldFormatsRegistry {
init(
getConfig: FieldFormatsGetConfigFn,
metaParamsOptions: Record<string, any> = {},
defaultFieldConverters: IFieldFormatType[] = baseFormatters
defaultFieldConverters: FieldFormatInstanceType[] = baseFormatters
) {
const defaultTypeMap = getConfig('format:defaultTypeMap');
this.register(defaultFieldConverters);
@@ -79,23 +79,23 @@ export class FieldFormatsRegistry {
* Get a derived FieldFormat class by its id.
*
* @param {FieldFormatId} formatId - the format id
* @return {IFieldFormatType | undefined}
* @return {FieldFormatInstanceType | undefined}
*/
getType = (formatId: FieldFormatId): IFieldFormatType | undefined => {
getType = (formatId: FieldFormatId): FieldFormatInstanceType | undefined => {
const fieldFormat = this.fieldFormats.get(formatId);

if (fieldFormat) {
const decoratedFieldFormat: any = this.fieldFormatMetaParamsDecorator(fieldFormat);

if (decoratedFieldFormat) {
return decoratedFieldFormat as IFieldFormatType;
return decoratedFieldFormat as FieldFormatInstanceType;
}
}

return undefined;
};

getTypeWithoutMetaParams = (formatId: FieldFormatId): IFieldFormatType | undefined => {
getTypeWithoutMetaParams = (formatId: FieldFormatId): FieldFormatInstanceType | undefined => {
return this.fieldFormats.get(formatId);
};

@@ -106,12 +106,12 @@ export class FieldFormatsRegistry {
*
* @param {KBN_FIELD_TYPES} fieldType
* @param {ES_FIELD_TYPES[]} esTypes - Array of ES data types
* @return {IFieldFormatType | undefined}
* @return {FieldFormatInstanceType | undefined}
*/
getDefaultType = (
fieldType: KBN_FIELD_TYPES,
esTypes: ES_FIELD_TYPES[]
): IFieldFormatType | undefined => {
): FieldFormatInstanceType | undefined => {
const config = this.getDefaultConfig(fieldType, esTypes);

return this.getType(config.id);
@@ -206,14 +206,16 @@ export class FieldFormatsRegistry {
* Get filtered list of field formats by format type
*
* @param {KBN_FIELD_TYPES} fieldType
* @return {IFieldFormatType[]}
* @return {FieldFormatInstanceType[]}
*/
getByFieldType(fieldType: KBN_FIELD_TYPES): IFieldFormatType[] {
getByFieldType(fieldType: KBN_FIELD_TYPES): FieldFormatInstanceType[] {
return [...this.fieldFormats.values()]
.filter((format: IFieldFormatType) => format && format.fieldType.indexOf(fieldType) !== -1)
.filter(
(format: FieldFormatInstanceType) => format && format.fieldType.indexOf(fieldType) !== -1
)
.map(
(format: IFieldFormatType) =>
this.fieldFormatMetaParamsDecorator(format) as IFieldFormatType
(format: FieldFormatInstanceType) =>
this.fieldFormatMetaParamsDecorator(format) as FieldFormatInstanceType
);
}

@@ -238,20 +240,20 @@ export class FieldFormatsRegistry {
});
}

register(fieldFormats: IFieldFormatType[]) {
register(fieldFormats: FieldFormatInstanceType[]) {
fieldFormats.forEach(fieldFormat => this.fieldFormats.set(fieldFormat.id, fieldFormat));
}

/**
* FieldFormat decorator - provide a one way to add meta-params for all field formatters
*
* @private
* @param {IFieldFormatType} fieldFormat - field format type
* @return {IFieldFormatType | undefined}
* @param {FieldFormatInstanceType} fieldFormat - field format type
* @return {FieldFormatInstanceType | undefined}
*/
private fieldFormatMetaParamsDecorator = (
fieldFormat: IFieldFormatType
): IFieldFormatType | undefined => {
fieldFormat: FieldFormatInstanceType
): FieldFormatInstanceType | undefined => {
const getMetaParams = (customParams: Record<string, any>) => this.buildMetaParams(customParams);

if (fieldFormat) {
2 changes: 1 addition & 1 deletion src/plugins/data/common/field_formats/index.ts
Original file line number Diff line number Diff line change
@@ -52,6 +52,6 @@ export {
FieldFormatConfig,
FieldFormatId,
// Used in data plugin only
IFieldFormatType,
FieldFormatInstanceType,
IFieldFormat,
} from './types';
6 changes: 3 additions & 3 deletions src/plugins/data/common/field_formats/types.ts
Original file line number Diff line number Diff line change
@@ -16,9 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/

import { FieldFormat } from './field_format';
export { FieldFormat };

/** @public **/
export type FieldFormatsContentType = 'html' | 'text';
@@ -82,10 +80,12 @@ export type IFieldFormat = PublicMethodsOf<FieldFormat>;
*/
export type FieldFormatId = FIELD_FORMAT_IDS | string;

export type IFieldFormatType = (new (
/** @internal **/
export type FieldFormatInstanceType = (new (
params?: any,
getConfig?: FieldFormatsGetConfigFn
) => FieldFormat) & {
// Static properties:
id: FieldFormatId;
title: string;
fieldType: string | string[];
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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.
*/

import { contains } from 'lodash';
import React from 'react';
import { History } from 'history';
import { i18n } from '@kbn/i18n';
import { EuiCallOut } from '@elastic/eui';
import { CoreStart } from 'kibana/public';
import { toMountPoint } from '../../../../kibana_react/public';
import { IndexPatternsContract } from './index_patterns';

export type EnsureDefaultIndexPattern = (history: History) => Promise<unknown> | undefined;

export const createEnsureDefaultIndexPattern = (core: CoreStart) => {
let bannerId: string;
let timeoutId: NodeJS.Timeout | undefined;

/**
* Checks whether a default index pattern is set and exists and defines
* one otherwise.
*
* If there are no index patterns, redirect to management page and show
* banner. In this case the promise returned from this function will never
* resolve to wait for the URL change to happen.
*/
return async function ensureDefaultIndexPattern(this: IndexPatternsContract, history: History) {
const patterns = await this.getIds();
let defaultId = core.uiSettings.get('defaultIndex');
let defined = !!defaultId;
const exists = contains(patterns, defaultId);

if (defined && !exists) {
core.uiSettings.remove('defaultIndex');
defaultId = defined = false;
}

if (defined) {
return;
}

// If there is any index pattern created, set the first as default
if (patterns.length >= 1) {
defaultId = patterns[0];
core.uiSettings.set('defaultIndex', defaultId);
} else {
const canManageIndexPatterns = core.application.capabilities.management.kibana.index_patterns;
const redirectTarget = canManageIndexPatterns ? '/management/kibana/index_pattern' : '/home';

if (timeoutId) {
clearTimeout(timeoutId);
}

// Avoid being hostile to new users who don't have an index pattern setup yet
// give them a friendly info message instead of a terse error message
bannerId = core.overlays.banners.replace(
bannerId,
toMountPoint(
<EuiCallOut
color="warning"
iconType="iInCircle"
title={i18n.translate('data.indexPatterns.ensureDefaultIndexPattern.bannerLabel', {
defaultMessage:
"In order to visualize and explore data in Kibana, you'll need to create an index pattern to retrieve data from Elasticsearch.",
})}
/>
)
);

// hide the message after the user has had a chance to acknowledge it -- so it doesn't permanently stick around
timeoutId = setTimeout(() => {
core.overlays.banners.remove(bannerId);
timeoutId = undefined;
}, 15000);

history.push(redirectTarget);

// return never-resolving promise to stop resolving and wait for the url change
return new Promise(() => {});
}
};
};
Original file line number Diff line number Diff line change
@@ -21,9 +21,9 @@
import { IndexPatternsService } from './index_patterns';
import {
SavedObjectsClientContract,
IUiSettingsClient,
HttpSetup,
SavedObjectsFindResponsePublic,
CoreStart,
} from 'kibana/public';

jest.mock('./index_pattern', () => {
@@ -61,10 +61,10 @@ describe('IndexPatterns', () => {
}) as Promise<SavedObjectsFindResponsePublic<any>>
);

const uiSettings = {} as IUiSettingsClient;
const core = {} as CoreStart;
const http = {} as HttpSetup;

indexPatterns = new IndexPatternsService(uiSettings, savedObjectsClient, http);
indexPatterns = new IndexPatternsService(core, savedObjectsClient, http);
});

test('does cache gets for the same id', async () => {
Original file line number Diff line number Diff line change
@@ -22,11 +22,16 @@ import {
SimpleSavedObject,
IUiSettingsClient,
HttpStart,
CoreStart,
} from 'src/core/public';

import { createIndexPatternCache } from './_pattern_cache';
import { IndexPattern } from './index_pattern';
import { IndexPatternsApiClient, GetFieldsOptions } from './index_patterns_api_client';
import {
createEnsureDefaultIndexPattern,
EnsureDefaultIndexPattern,
} from './ensure_default_index_pattern';

const indexPatternCache = createIndexPatternCache();

@@ -37,15 +42,13 @@ export class IndexPatternsService {
private savedObjectsClient: SavedObjectsClientContract;
private savedObjectsCache?: Array<SimpleSavedObject<Record<string, any>>> | null;
private apiClient: IndexPatternsApiClient;
ensureDefaultIndexPattern: EnsureDefaultIndexPattern;

constructor(
config: IUiSettingsClient,
savedObjectsClient: SavedObjectsClientContract,
http: HttpStart
) {
constructor(core: CoreStart, savedObjectsClient: SavedObjectsClientContract, http: HttpStart) {
this.apiClient = new IndexPatternsApiClient(http);
this.config = config;
this.config = core.uiSettings;
this.savedObjectsClient = savedObjectsClient;
this.ensureDefaultIndexPattern = createEnsureDefaultIndexPattern(core);
}

private async refreshSavedObjectsCache() {
1 change: 1 addition & 0 deletions src/plugins/data/public/mocks.ts
Original file line number Diff line number Diff line change
@@ -57,6 +57,7 @@ const createStartContract = (): Start => {
SearchBar: jest.fn(),
},
indexPatterns: ({
ensureDefaultIndexPattern: jest.fn(),
make: () => ({
fieldsFetcher: {
fetchForWildcard: jest.fn(),
3 changes: 2 additions & 1 deletion src/plugins/data/public/plugin.ts
Original file line number Diff line number Diff line change
@@ -139,6 +139,7 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
return {
autocomplete: this.autocomplete.setup(core),
search: this.searchService.setup(core, {
expressions,
getInternalStartServices,
packageInfo: this.packageInfo,
query: queryService,
@@ -159,7 +160,7 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
const fieldFormats = this.fieldFormatsService.start();
setFieldFormats(fieldFormats);

const indexPatterns = new IndexPatternsService(uiSettings, savedObjects.client, http);
const indexPatterns = new IndexPatternsService(core, savedObjects.client, http);
setIndexPatterns(indexPatterns);

const query = this.queryService.start(savedObjects);
19 changes: 6 additions & 13 deletions src/plugins/data/public/public.api.md
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ import { EuiConfirmModalProps } from '@elastic/eui';
import { EuiFieldText } from '@elastic/eui';
import { EuiGlobalToastListToast } from '@elastic/eui';
import { ExclusiveUnion } from '@elastic/eui';
import { ExpressionAstFunction } from 'src/plugins/expressions/public';
import { ExpressionsSetup } from 'src/plugins/expressions/public';
import { History } from 'history';
import { HttpSetup } from 'src/core/public';
@@ -59,21 +60,13 @@ import { Unit } from '@elastic/datemath';
import { UnregisterCallback } from 'history';
import { UserProvidedValues } from 'src/core/server/types';

// Warning: (ae-forgotten-export) The symbol "AggConfigSerialized" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "AggConfigOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface AggConfigOptions {
// (undocumented)
enabled?: boolean;
// (undocumented)
id?: string;
// (undocumented)
params?: Record<string, any>;
// (undocumented)
schema?: string;
// (undocumented)
export type AggConfigOptions = Assign<AggConfigSerialized, {
type: IAggType;
}
}>;

// Warning: (ae-missing-release-tag) "AggGroupNames" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -112,7 +105,7 @@ export class AggParamType<TAggConfig extends IAggConfig = IAggConfig> extends Ba
// (undocumented)
allowedAggs: string[];
// (undocumented)
makeAgg: (agg: TAggConfig, state?: any) => TAggConfig;
makeAgg: (agg: TAggConfig, state?: AggConfigSerialized) => TAggConfig;
}

// Warning: (ae-missing-release-tag) "AggTypeFieldFilters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -145,7 +138,7 @@ export class AggTypeFilters {
// Warning: (ae-missing-release-tag) "baseFormattersPublic" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const baseFormattersPublic: (import("../../common").IFieldFormatType | typeof DateFormat)[];
export const baseFormattersPublic: (import("../../common").FieldFormatInstanceType | typeof DateFormat)[];

// Warning: (ae-missing-release-tag) "BUCKET_TYPES" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
218 changes: 210 additions & 8 deletions src/plugins/data/public/search/aggs/agg_config.test.ts
Original file line number Diff line number Diff line change
@@ -24,18 +24,21 @@ import { AggConfigs, CreateAggConfigParams } from './agg_configs';
import { AggType } from './agg_type';
import { AggTypesRegistryStart } from './agg_types_registry';
import { mockDataServices, mockAggTypesRegistry } from './test_helpers';
import { MetricAggType } from './metrics/metric_agg_type';
import { Field as IndexPatternField, IndexPattern } from '../../index_patterns';
import { stubIndexPatternWithFields } from '../../../public/stubs';
import { FieldFormatsStart } from '../../field_formats';
import { fieldFormatsServiceMock } from '../../field_formats/mocks';

describe('AggConfig', () => {
let indexPattern: IndexPattern;
let typesRegistry: AggTypesRegistryStart;
const fieldFormats = fieldFormatsServiceMock.createStartContract();
let fieldFormats: FieldFormatsStart;

beforeEach(() => {
jest.restoreAllMocks();
mockDataServices();
fieldFormats = fieldFormatsServiceMock.createStartContract();
indexPattern = stubIndexPatternWithFields as IndexPattern;
typesRegistry = mockAggTypesRegistry();
});
@@ -325,7 +328,7 @@ describe('AggConfig', () => {
});
});

describe('#toJSON', () => {
describe('#serialize', () => {
it('includes the aggs id, params, type and schema', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const configStates = {
@@ -342,7 +345,7 @@ describe('AggConfig', () => {
expect(aggConfig.type).toHaveProperty('name', 'date_histogram');
expect(typeof aggConfig.schema).toBe('string');

const state = aggConfig.toJSON();
const state = aggConfig.serialize();
expect(state).toHaveProperty('id', '1');
expect(typeof state.params).toBe('object');
expect(state).toHaveProperty('type', 'date_histogram');
@@ -367,6 +370,201 @@ describe('AggConfig', () => {
});
});

describe('#toExpressionAst', () => {
beforeEach(() => {
fieldFormats.getDefaultInstance = (() => ({
getConverterFor: (t?: string) => t || identity,
})) as any;
indexPattern.fields.getByName = name =>
({
format: {
getConverterFor: (t?: string) => t || identity,
},
} as IndexPatternField);
});

it('works with primitive param types', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const configStates = {
enabled: true,
type: 'terms',
schema: 'segment',
params: {
field: 'machine.os.keyword',
order: 'asc',
},
};
const aggConfig = ac.createAggConfig(configStates);
expect(aggConfig.toExpressionAst()).toMatchInlineSnapshot(`
Object {
"arguments": Object {
"enabled": Array [
true,
],
"id": Array [
"1",
],
"missingBucket": Array [
false,
],
"missingBucketLabel": Array [
"Missing",
],
"order": Array [
"asc",
],
"otherBucket": Array [
false,
],
"otherBucketLabel": Array [
"Other",
],
"schema": Array [
"segment",
],
"size": Array [
5,
],
},
"function": "aggTerms",
"type": "function",
}
`);
});

it('creates a subexpression for params of type "agg"', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const configStates = {
type: 'terms',
params: {
field: 'machine.os.keyword',
order: 'asc',
orderAgg: {
enabled: true,
type: 'terms',
params: {
field: 'bytes',
order: 'asc',
size: 5,
},
},
},
};
const aggConfig = ac.createAggConfig(configStates);
const aggArg = aggConfig.toExpressionAst()?.arguments.orderAgg;
expect(aggArg).toMatchInlineSnapshot(`
Array [
Object {
"chain": Array [
Object {
"arguments": Object {
"enabled": Array [
true,
],
"id": Array [
"1-orderAgg",
],
"missingBucket": Array [
false,
],
"missingBucketLabel": Array [
"Missing",
],
"order": Array [
"asc",
],
"otherBucket": Array [
false,
],
"otherBucketLabel": Array [
"Other",
],
"schema": Array [
"orderAgg",
],
"size": Array [
5,
],
},
"function": "aggTerms",
"type": "function",
},
],
"type": "expression",
},
]
`);
});

it('creates a subexpression for param types other than "agg" which have specified toExpressionAst', () => {
// Overwrite the `ranges` param in the `range` agg with a mock toExpressionAst function
const range: MetricAggType = typesRegistry.get('range');
range.expressionName = 'aggRange';
const rangesParam = range.params.find(p => p.name === 'ranges');
rangesParam!.toExpressionAst = (val: any) => ({
type: 'function',
function: 'aggRanges',
arguments: {
ranges: ['oh hi there!'],
},
});

const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const configStates = {
type: 'range',
params: {
field: 'bytes',
},
};

const aggConfig = ac.createAggConfig(configStates);
const ranges = aggConfig.toExpressionAst()!.arguments.ranges;
expect(ranges).toMatchInlineSnapshot(`
Array [
Object {
"chain": Array [
Object {
"arguments": Object {
"ranges": Array [
"oh hi there!",
],
},
"function": "aggRanges",
"type": "function",
},
],
"type": "expression",
},
]
`);
});

it('stringifies any other params which are an object', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const configStates = {
type: 'terms',
params: {
field: 'machine.os.keyword',
order: 'asc',
json: { foo: 'bar' },
},
};
const aggConfig = ac.createAggConfig(configStates);
const json = aggConfig.toExpressionAst()?.arguments.json;
expect(json).toEqual([JSON.stringify(configStates.params.json)]);
});

it(`returns undefined if an expressionName doesn't exist on the agg type`, () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const configStates = {
type: 'unknown type',
params: {},
};
const aggConfig = ac.createAggConfig(configStates);
expect(aggConfig.toExpressionAst()).toBe(undefined);
});
});

describe('#makeLabel', () => {
let aggConfig: AggConfig;

@@ -422,6 +620,9 @@ describe('AggConfig', () => {
let aggConfig: AggConfig;

beforeEach(() => {
fieldFormats.getDefaultInstance = (() => ({
getConverterFor: (t?: string) => t || identity,
})) as any;
indexPattern.fields.getByName = name =>
({
format: {
@@ -434,18 +635,19 @@ describe('AggConfig', () => {
type: 'histogram',
schema: 'bucket',
params: {
field: {
format: {
getConverterFor: (t?: string) => t || identity,
},
},
field: 'bytes',
},
};
const ac = new AggConfigs(indexPattern, [configStates], { typesRegistry, fieldFormats });
aggConfig = ac.createAggConfig(configStates);
});

it("returns the field's formatter", () => {
aggConfig.params.field = {
format: {
getConverterFor: (t?: string) => t || identity,
},
};
expect(aggConfig.fieldFormatter().toString()).toBe(
aggConfig
.getField()
Loading

0 comments on commit a6b014b

Please sign in to comment.