Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
d614e19
Add get Discover session function
davismcphee Jul 9, 2025
2bbae78
Rename DiscoverSessionView to SingleTabView
davismcphee Jul 10, 2025
95c95ab
Fix InternalStateDispatch type
davismcphee Jul 10, 2025
4572b4f
Loading Discover session when initializing tabs
davismcphee Jul 11, 2025
d9dfe92
Remove unused state
davismcphee Jul 11, 2025
5485392
Start moving session initialization to main route
davismcphee Jul 12, 2025
fdaec72
Fix not found error handling
davismcphee Jul 12, 2025
9105bec
Fix tabs initialization
davismcphee Jul 12, 2025
cccce03
Update naming in initializeSession
davismcphee Jul 12, 2025
091e2b3
Update initializeSession thunk naming
davismcphee Jul 12, 2025
087a611
Fix tests
davismcphee Jul 12, 2025
291b559
Fix types
davismcphee Jul 12, 2025
e88ff54
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Jul 12, 2025
8de9ca2
Fix i18n
davismcphee Jul 14, 2025
36d87f7
Support loading multi-tab sessions
davismcphee Jul 15, 2025
5e55211
Fix react markdown import
davismcphee Jul 15, 2025
beaed7f
Don't reload saved search when initializing tab
davismcphee Jul 16, 2025
3792dfd
Fix URL state being overwritten when refreshing page with saved tab
davismcphee Jul 16, 2025
8785f5c
Make discover session ID required
davismcphee Jul 16, 2025
cd93173
Type fixes
davismcphee Jul 21, 2025
d91f6d0
Working on Discover session saving
davismcphee Jul 22, 2025
4d49fa9
More work on saving
davismcphee Jul 26, 2025
a2981d0
Prefix ref names
davismcphee Jul 26, 2025
55c25c2
Make restoring local tabs work with persisted discover sessions
davismcphee Jul 26, 2025
2c1ebef
Fix discover session breadcrumb disappearing when switching to unsave…
davismcphee Jul 26, 2025
5d7bf9e
Persist serialized search source locally
davismcphee Jul 28, 2025
86da074
Support restoring locally persisted ad hoc data views in tabs
davismcphee Jul 29, 2025
ddbbd83
Fix mock type
davismcphee Jul 29, 2025
0e7db64
Initial Discover session saving
davismcphee Jul 30, 2025
150fd77
Fix time range saving
davismcphee Jul 30, 2025
bb1d4b9
Return save response
davismcphee Jul 30, 2025
00954fe
Sync tab global state with URL and global services
davismcphee Jul 30, 2025
0d5cd94
Replace usages of global state container and remove it
davismcphee Jul 31, 2025
4520b22
Rename lastPersistedGlobalState to globalState
davismcphee Jul 31, 2025
1d50347
Remove re-passing global state to middleware
davismcphee Jul 31, 2025
4521be0
Simplify local tab syncing
davismcphee Jul 31, 2025
878e7ff
Change setTabGlobal state to setGlobatState
davismcphee Jul 31, 2025
fddf270
Remove initialGlobalState
davismcphee Jul 31, 2025
fa94632
Add mapping utils
davismcphee Aug 1, 2025
fb17d24
Fix types
davismcphee Aug 1, 2025
cff4066
More work on saving
davismcphee Aug 1, 2025
365eeff
Make sure to undo saved search changes after saving
davismcphee Aug 1, 2025
8cb9448
Finish ad hoc data view cloning logic
davismcphee Aug 1, 2025
fd47969
Change undoSavedSearchChanges not to rely on global services
davismcphee Aug 1, 2025
1dd7dd9
Small fix when reverting saved search
davismcphee Aug 1, 2025
c6479a8
Finish initial save implementation
davismcphee Aug 5, 2025
ad480b6
Fix URL being cleared out after saving discover session
davismcphee Aug 5, 2025
bd92ba9
Fix time range resetting after saving without time restore
davismcphee Aug 5, 2025
e75af6e
Fix issue where saving with default profile ad hoc data view causes u…
davismcphee Aug 6, 2025
f349df9
Fix saved search plugin bundle size
davismcphee Aug 6, 2025
88abaff
Clean up saved search plugin folder structure
davismcphee Aug 6, 2025
b353b4a
Restore fromSavedSearchAttributes export
davismcphee Aug 6, 2025
b3dccbe
Fix issue where switching between a base session and copy-on-saved se…
davismcphee Aug 6, 2025
c929222
Fix issue where chart disappears on save
davismcphee Aug 6, 2025
9ad5209
Make sure locally persisted discover session ID is synced when it cha…
davismcphee Aug 7, 2025
b4cb687
Fix merge conflicts
davismcphee Aug 7, 2025
72d5492
Fix type
davismcphee Aug 7, 2025
6e0b7b5
Fix import path
lukasolson Aug 14, 2025
1b9a3f0
[Discover] Address jest tests
jughosta Aug 15, 2025
07b73fd
[Discover] Address jest tests
jughosta Aug 15, 2025
c780be8
Update snapshots
davismcphee Aug 19, 2025
af676bf
Fix global state syncing in tests
davismcphee Aug 19, 2025
aa16c9e
Fixing discover state tests
davismcphee Aug 19, 2025
66bb3e9
Simplify getDiscoverStateMock
davismcphee Aug 19, 2025
91809d5
Fix discover state tests
davismcphee Aug 20, 2025
56b949d
Remove unused param
davismcphee Aug 20, 2025
1028670
discover state test cleanup
davismcphee Aug 20, 2025
91aef31
Improve restoreStateFromSavedSearch
davismcphee Aug 20, 2025
db13229
Remove TABS_ENABLED
davismcphee Aug 20, 2025
d9bb6ca
Fix request count tests
davismcphee Aug 20, 2025
6f5e1b7
Remove unnecessary cast
davismcphee Aug 20, 2025
ce242d8
Remove on_save_search.tsx
davismcphee Aug 20, 2025
0493bc4
Minor discover state test change
davismcphee Aug 20, 2025
61233d2
Fix discover session not found error handling
davismcphee Aug 20, 2025
9b9c80d
Fix ad hoc data view cloning for ES|QL tabs
davismcphee Aug 20, 2025
f88be2e
Remove syncStateForTesting
davismcphee Aug 21, 2025
e85e31b
Fix global state initialization
davismcphee Aug 21, 2025
9dba4d4
Small cleanup
davismcphee Aug 21, 2025
57f8d93
Fix jest tests
davismcphee Aug 21, 2025
5c9bf55
Removing dead code
davismcphee Aug 21, 2025
b710df3
Finish fixing tests
davismcphee Aug 21, 2025
73a99d7
Add extractReferences tests
davismcphee Aug 22, 2025
4b3aa8d
Add createDataSource test
davismcphee Aug 22, 2025
00d5923
Add onSaveDiscoverSession tests
davismcphee Aug 22, 2025
3f78abd
Finish onSaveDiscoverSession tests
davismcphee Aug 23, 2025
0e90f1f
Revert unnecessary i18n change
davismcphee Aug 23, 2025
ae1d6a8
Add tab mapping utils tests
davismcphee Aug 23, 2025
4b41136
Small fix to serializeError
davismcphee Aug 23, 2025
0e888b8
Merge branch 'main' into discover-tabs-saving-poc
davismcphee Aug 28, 2025
c9ddf88
Small fix to tab preview
davismcphee Aug 29, 2025
a1c0fda
Add tabs saving and loading functional tests
davismcphee Aug 29, 2025
cf148ca
Add another functional test
davismcphee Aug 29, 2025
b494036
Merge branch 'main' into discover-tabs-saving-poc
kertal Sep 1, 2025
e8dd2d3
Merge branch 'main' into discover-tabs-saving-poc
davismcphee Sep 1, 2025
816ef88
Fix functional tests
davismcphee Sep 2, 2025
0168ca8
Add saveDiscoverSession tests
davismcphee Sep 2, 2025
61840c6
Update tabs storage manager tests
davismcphee Sep 2, 2025
0b19730
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Sep 2, 2025
4eceea9
Test type fixes
davismcphee Sep 2, 2025
945bd85
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Sep 2, 2025
6b59e4d
Merge branch 'main' into discover-tabs-saving-poc
davismcphee Sep 3, 2025
926460d
Clean up createDataSource
davismcphee Sep 3, 2025
ffbb16e
Clean up isTimeBased tests
davismcphee Sep 3, 2025
093348a
Small discover_state.test.ts cleanups
davismcphee Sep 3, 2025
0ef6c01
Split out discover session save modal
davismcphee Sep 3, 2025
b9835af
Make boolean condition clearer
davismcphee Sep 3, 2025
435d5c0
Fix test flakiness
davismcphee Sep 3, 2025
460014c
Don't omit services
davismcphee Sep 3, 2025
aab9428
Merge branch 'main' into discover-tabs-saving-poc
davismcphee Sep 5, 2025
8837251
Merge branch 'main' into discover-tabs-saving-poc
davismcphee Sep 8, 2025
49badc5
Add max tabs count in Discover
davismcphee Sep 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ pageLoadAssetSize:
savedObjectsManagement: 22426
savedObjectsTagging: 23144
savedObjectsTaggingOss: 2163
savedSearch: 12662
savedSearch: 11000
screenshotMode: 2351
screenshotting: 8417
searchAssistant: 6150
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const loadDashboardState = async ({
})
.catch((e) => {
if (e.response?.status === 404) {
throw new SavedObjectNotFound(DASHBOARD_CONTENT_ID, id);
throw new SavedObjectNotFound({ type: DASHBOARD_CONTENT_ID, id });
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Small change to SavedObjectNotFound constructor to fix an issue with SO not found redirects.

}
const message = (e.body as { message?: string })?.message ?? e.message;
throw new Error(message);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { extractReferences } from './extract_references';
import type { SerializedSearchSourceFields } from './types';

describe('extractReferences', () => {
it('should extract reference for data view ID', () => {
const searchSource: SerializedSearchSourceFields = {
index: 'test-index',
};
const result = extractReferences(searchSource);
expect(result).toEqual([
{
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
},
[
{
id: 'test-index',
name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
type: 'index-pattern',
},
],
]);
});

it('should not extract reference for data view spec', () => {
const searchSource: SerializedSearchSourceFields = {
index: {
id: 'test-id',
title: 'test-title',
},
};
const result = extractReferences(searchSource);
expect(result).toEqual([
{
index: {
id: 'test-id',
title: 'test-title',
},
},
[],
]);
});

it('should extract reference for filter', () => {
const searchSource: SerializedSearchSourceFields = {
filter: [
{
meta: {
index: 'test-index',
},
},
],
};
const result = extractReferences(searchSource);
expect(result).toEqual([
{
filter: [
{
meta: {
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
},
},
],
},
[
{
id: 'test-index',
name: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
type: 'index-pattern',
},
],
]);
});

it('should apply prefix to references', () => {
const searchSource: SerializedSearchSourceFields = {
index: 'test-index',
filter: [
{
meta: {
index: 'test-index',
},
},
],
};
const result = extractReferences(searchSource, { refNamePrefix: 'testPrefix' });
expect(result).toEqual([
{
indexRefName: 'testPrefix.kibanaSavedObjectMeta.searchSourceJSON.index',
filter: [
{
meta: {
indexRefName:
'testPrefix.kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
},
},
],
},
[
{
id: 'test-index',
name: 'testPrefix.kibanaSavedObjectMeta.searchSourceJSON.index',
type: 'index-pattern',
},
{
id: 'test-index',
name: 'testPrefix.kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
type: 'index-pattern',
},
],
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ import type { SerializedSearchSourceFields } from './types';
import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../..';

export const extractReferences = (
state: SerializedSearchSourceFields
state: SerializedSearchSourceFields,
options?: { refNamePrefix?: string }
): [SerializedSearchSourceFields, SavedObjectReference[]] => {
const refNamePrefix = options?.refNamePrefix ? `${options.refNamePrefix}.` : '';
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This approach seems to work reliably for generating unique ref names when saving multiple search sources within a multi-tab Discover session. The existing inject logic already doesn't care about the actual ref names, so no special logic needed there.

let searchSourceFields: SerializedSearchSourceFields & { indexRefName?: string } = { ...state };
const references: SavedObjectReference[] = [];
if (searchSourceFields.index) {
if (typeof searchSourceFields.index === 'string') {
const indexId = searchSourceFields.index;
const refName = 'kibanaSavedObjectMeta.searchSourceJSON.index';
const refName = `${refNamePrefix}kibanaSavedObjectMeta.searchSourceJSON.index`;
references.push({
name: refName,
type: DATA_VIEW_SAVED_OBJECT_TYPE,
Expand All @@ -47,7 +49,7 @@ export const extractReferences = (
if (!filterRow.meta || !filterRow.meta.index) {
return filterRow;
}
const refName = `kibanaSavedObjectMeta.searchSourceJSON.filter[${i}].meta.index`;
const refName = `${refNamePrefix}kibanaSavedObjectMeta.searchSourceJSON.filter[${i}].meta.index`;
references.push({
name: refName,
type: DATA_VIEW_SAVED_OBJECT_TYPE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ describe('IndexPatterns', () => {
test('savedObjectCache pre-fetches title, type, typeMeta', async () => {
expect(await indexPatterns.getIds()).toEqual(['id']);
expect(savedObjectsClient.find).toHaveBeenCalledWith({
fields: ['title', 'type', 'typeMeta', 'name'],
fields: ['title', 'type', 'typeMeta', 'name', 'timeFieldName'],
perPage: 10000,
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,7 @@ const createFetchFieldErrorTitle = ({ id, title }: { id?: string; title?: string
*/
export type DataViewSavedObjectAttrs = Pick<
DataViewAttributes,
'title' | 'type' | 'typeMeta' | 'name'
>;

export type IndexPatternListSavedObjectAttrs = Pick<
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Dead code.

DataViewAttributes,
'title' | 'type' | 'typeMeta' | 'name'
'title' | 'type' | 'typeMeta' | 'name' | 'timeFieldName'
>;

/**
Expand All @@ -87,7 +82,14 @@ export interface DataViewListItem {
* Data view type meta
*/
typeMeta?: TypeMeta;
/**
* Human-readable name
*/
name?: string;
/**
* Time field name if applicable
*/
timeFieldName?: string;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I needed a way to know the timeFieldName values of data views which hadn't been fully loaded and only existed in the data view picker list, and couldn't think of a better way to do it. An extra prop on list items seemed like a small price to pay.

}

/**
Expand Down Expand Up @@ -404,7 +406,7 @@ export class DataViewsService {
*/
private async refreshSavedObjectsCache() {
const so = await this.savedObjectsClient.find({
fields: ['title', 'type', 'typeMeta', 'name'],
fields: ['title', 'type', 'typeMeta', 'name', 'timeFieldName'],
perPage: 10000,
});
this.savedObjectsCache = so;
Expand Down Expand Up @@ -494,6 +496,7 @@ export class DataViewsService {
type: obj?.attributes?.type,
typeMeta: obj?.attributes?.typeMeta && JSON.parse(obj?.attributes?.typeMeta),
name: obj?.attributes?.name,
timeFieldName: obj?.attributes?.timeFieldName,
}));
};

Expand Down Expand Up @@ -1269,7 +1272,7 @@ export class DataViewsService {
})) as SavedObject<DataViewAttributes>;

if (this.savedObjectsCache) {
this.savedObjectsCache.push(response as SavedObject<IndexPatternListSavedObjectAttrs>);
this.savedObjectsCache.push(response);
}
dataView.version = response.version;
dataView.namespaces = response.namespaces || [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ export class ContentMagementWrapper implements PersistenceAPI {
});
} catch (e) {
if (e.body?.statusCode === 404) {
throw new SavedObjectNotFound('data view', id, 'management/kibana/dataViews');
throw new SavedObjectNotFound({
type: DataViewSOType,
typeDisplayName: 'data view',
Comment on lines +62 to +63
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was the issue with data view redirects. At some point we changed the type to data view, presumably to update the error message when we renamed index patterns, but it broke the redirect functionality.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You mean this issue?
#203405

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I wasn't aware we already had an issue for it, but yes these changes fix that!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jughosta this seems to be a different one, about missing Discover session, but it should also be improved 👍

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it seems this PR resolves #203405 🥳

Image

id,
link: '/app/management/kibana/dataViews',
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Plus the link itself was outdated and didn't go anywhere...

});
} else {
throw e;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ describe('createDataSource', () => {
const result = createDataSource({ dataView, query });
expect(result).toEqual(undefined);
});

it('should return data view source when not ES|QL query and passed a dataView id directly', () => {
const query = { language: 'kql', query: 'test' };
const result = createDataSource({ dataView: 'test', query });
expect(result).toEqual(createDataViewDataSource({ dataViewId: 'test' }));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import { isOfAggregateQueryType, type AggregateQuery, type Query } from '@kbn/es-query';
import type { DataView } from '@kbn/data-views-plugin/common';
import type { DataView, DataViewSpec } from '@kbn/data-views-plugin/common';
import {
DataSourceType,
type DataViewDataSource,
Expand All @@ -33,14 +33,19 @@ export const createDataSource = ({
dataView,
query,
}: {
dataView: DataView | undefined;
dataView: DataView | DataViewSpec | string | undefined;
query: Query | AggregateQuery | undefined;
}) => {
return isOfAggregateQueryType(query)
? createEsqlDataSource()
: dataView?.id
? createDataViewDataSource({ dataViewId: dataView.id })
: undefined;
if (isOfAggregateQueryType(query)) {
return createEsqlDataSource();
}
if (typeof dataView === 'string') {
return createDataViewDataSource({ dataViewId: dataView });
}
if (dataView?.id) {
return createDataViewDataSource({ dataViewId: dataView.id });
}
return undefined;
Comment on lines +39 to +48
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you for simplifying it instead of extending the chaining. This is much more readable

};

export const isDataSourceType = <T extends DataSourceType>(
Expand Down
Loading