Skip to content

Commit

Permalink
[Discover] Adding Recent Datasets (#8133)
Browse files Browse the repository at this point in the history
* Adding recent datasets to dataset selector

Signed-off-by: Sean Li <lnse@amazon.com>

* addressing comments, adding tests

Signed-off-by: Sean Li <lnse@amazon.com>

* moving recent datasets to fetched datasets

Signed-off-by: Sean Li <lnse@amazon.com>

* mocking UI settings for test

Signed-off-by: Sean Li <lnse@amazon.com>

* fixing connect_to_query_state.test

Signed-off-by: Sean Li <lnse@amazon.com>

* fixing sync_state_with_url test

Signed-off-by: Sean Li <lnse@amazon.com>

* adding recent datasets to session storage

Signed-off-by: Sean Li <lnse@amazon.com>

* fixing cache bug, improving code structure

Signed-off-by: Sean Li <lnse@amazon.com>

* adding i18n translation for group labels

Signed-off-by: Sean Li <lnse@amazon.com>

* updating mock

Signed-off-by: Sean Li <lnse@amazon.com>

* updating state sync tests and fixing typos in #8325

Signed-off-by: Sean Li <lnse@amazon.com>

* fixing dataset selector test

Signed-off-by: Sean Li <lnse@amazon.com>

* fixing index test

Signed-off-by: Sean Li <lnse@amazon.com>

---------

Signed-off-by: Sean Li <lnse@amazon.com>
(cherry picked from commit 464ef56)
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
github-actions[bot] committed Oct 11, 2024
1 parent 68c32e0 commit 2833351
Show file tree
Hide file tree
Showing 14 changed files with 185 additions and 31 deletions.
1 change: 1 addition & 0 deletions src/plugins/data/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export const UI_SETTINGS = {
SEARCH_INCLUDE_FROZEN: 'search:includeFrozen',
SEARCH_TIMEOUT: 'search:timeout',
SEARCH_INCLUDE_ALL_FIELDS: 'search:includeAllFields',
SEARCH_MAX_RECENT_DATASETS: 'search:maxRecentDatasets',
HISTOGRAM_BAR_TARGET: 'histogram:barTarget',
HISTOGRAM_MAX_BARS: 'histogram:maxBars',
HISTORY_LIMIT: 'history:limit',
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export class DataPublicPlugin
storage: this.storage,
sessionStorage: this.sessionStorage,
defaultSearchInterceptor: searchService.getDefaultSearchInterceptor(),
applicaton: core.application,
application: core.application,
});

uiActions.registerAction(
Expand Down Expand Up @@ -225,7 +225,7 @@ export class DataPublicPlugin
savedObjectsClient: savedObjects.client,
uiSettings,
indexPatterns,
applicaton: core.application,
application: core.application,
});
setQueryService(query);

Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data/public/query/query_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class QueryService {
storage,
uiSettings,
indexPatterns,
applicaton,
application,
}: QueryServiceStartDependencies): IQueryStart {
this.queryStringManager.getDatasetService().init(indexPatterns);
return {
Expand All @@ -110,7 +110,7 @@ export class QueryService {
savedQueries: createSavedQueryService(
savedObjectsClient,
this.queryStringManager,
applicaton
application
),
state$: this.state$,
timefilter: this.timefilter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const createSetupDatasetServiceMock = (): jest.Mocked<DatasetServiceContract> =>
getDefault: jest.fn().mockReturnValue(defaultDataset),
cacheDataset: jest.fn(),
fetchOptions: jest.fn(),
getRecentDatasets: jest.fn(),
addRecentDataset: jest.fn(),
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { DatasetService } from './dataset_service';
import { coreMock } from '../../../../../../core/public/mocks';
import { DEFAULT_DATA, DataStorage, Dataset } from 'src/plugins/data/common';
import { DEFAULT_DATA, DataStorage, Dataset, UI_SETTINGS } from 'src/plugins/data/common';
import { DataStructure } from '../../../../common';
import { IDataPluginServices } from '../../../types';
import { indexPatternTypeConfig } from './lib';
Expand All @@ -21,9 +21,13 @@ describe('DatasetService', () => {

beforeEach(() => {
uiSettings = coreMock.createSetup().uiSettings;
uiSettings.get = jest.fn().mockImplementation((setting: string) => {
if (setting === UI_SETTINGS.SEARCH_MAX_RECENT_DATASETS) {
return 4;
}
});
sessionStorage = new DataStorage(window.sessionStorage, 'opensearchDashboards.');
mockDataPluginServices = {} as jest.Mocked<IDataPluginServices>;

service = new DatasetService(uiSettings, sessionStorage);
indexPatterns = dataPluginMock.createStartContract().indexPatterns;
service.init(indexPatterns);
Expand Down Expand Up @@ -129,4 +133,53 @@ describe('DatasetService', () => {
expect(indexPatterns.create).toHaveBeenCalledTimes(0);
expect(indexPatterns.saveToCache).toHaveBeenCalledTimes(0);
});

test('addRecentDataset adds a dataset', () => {
const mockDataset1: Dataset = {
id: 'dataset1',
title: 'Dataset 1',
type: 'test-type',
timeFieldName: 'timestamp',
};

service.addRecentDataset(mockDataset1);
const recents = service.getRecentDatasets();
expect(recents).toContainEqual(mockDataset1);
expect(recents.length).toEqual(1);
expect(sessionStorage.get('recentDatasets')).toContainEqual(mockDataset1);
});

test('getRecentDatasets returns all datasets', () => {
for (let i = 0; i < 4; i++) {
service.addRecentDataset({
id: `dataset${i}`,
title: `Dataset ${i}`,
type: 'test-type',
timeFieldName: 'timestamp',
});
}
expect(service.getRecentDatasets().length).toEqual(4);
for (let i = 0; i < 4; i++) {
const mockDataset = {
id: `dataset${i}`,
title: `Dataset ${i}`,
type: 'test-type',
timeFieldName: 'timestamp',
};
expect(service.getRecentDatasets()).toContainEqual(mockDataset);
expect(sessionStorage.get('recentDatasets')).toContainEqual(mockDataset);
}
});

test('addRecentDatasets respects max size', () => {
for (let i = 0; i < 5; i++) {
service.addRecentDataset({
id: `dataset${i}`,
title: `Dataset ${i}`,
type: 'test-type',
timeFieldName: 'timestamp',
});
}
expect(service.getRecentDatasets().length).toEqual(4);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import { CoreStart } from 'opensearch-dashboards/public';
import LRUCache from 'lru-cache';
import {
Dataset,
DataStructure,
Expand All @@ -22,6 +23,7 @@ export class DatasetService {
private indexPatterns?: IndexPatternsContract;
private defaultDataset?: Dataset;
private typesRegistry: Map<string, DatasetTypeConfig> = new Map();
private recentDatasets: LRUCache<string, Dataset>;

constructor(
private readonly uiSettings: CoreStart['uiSettings'],
Expand All @@ -30,6 +32,10 @@ export class DatasetService {
if (this.uiSettings.get(UI_SETTINGS.QUERY_ENHANCEMENTS_ENABLED)) {
this.registerDefaultTypes();
}
this.recentDatasets = new LRUCache({
max: this.uiSettings.get(UI_SETTINGS.SEARCH_MAX_RECENT_DATASETS),
});
this.deserializeRecentDatasets();
}

/**
Expand Down Expand Up @@ -61,6 +67,30 @@ export class DatasetService {
return this.defaultDataset;
}

private serializeRecentDatasets(): void {
this.sessionStorage.set('recentDatasets', this.getRecentDatasets());
}

private deserializeRecentDatasets(): void {
const cacheData = this.sessionStorage.get('recentDatasets');
if (cacheData) {
cacheData.forEach((dataset: Dataset) => this.addRecentDataset(dataset, false));
}
}

public getRecentDatasets(): Dataset[] {
return this.recentDatasets.values();
}

public addRecentDataset(dataset: Dataset | undefined, serialize: boolean = true): void {
if (dataset) {
this.recentDatasets.set(dataset.id, dataset);
}
if (serialize) {
this.serializeRecentDatasets();
}
}

public async cacheDataset(dataset: Dataset): Promise<void> {
const type = this.getType(dataset.type);
if (dataset && dataset.type !== DEFAULT_DATA.SET_TYPES.INDEX_PATTERN) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ setupMock.uiSettings.get.mockImplementation((key: string) => {
return { pause: false, value: 0 };
case UI_SETTINGS.QUERY_ENHANCEMENTS_ENABLED:
return false;
case UI_SETTINGS.SEARCH_MAX_RECENT_DATASETS:
return 4;
default:
throw new Error(`sync_query test: not mocked uiSetting: ${key}`);
}
Expand Down Expand Up @@ -121,13 +123,16 @@ describe('connect_storage_to_query_state', () => {
queryService.setup({
uiSettings: setupMock.uiSettings,
storage: new DataStorage(window.localStorage, 'opensearch_dashboards.'),
sessionStorage: new DataStorage(window.sessionStorage, 'opensearch_dashboards.'),
defaultSearchInterceptor: mockSearchInterceptor,
application: setupMock.application,
});
queryServiceStart = queryService.start({
uiSettings: setupMock.uiSettings,
storage: new DataStorage(window.localStorage, 'opensearch_dashboards.'),
savedObjectsClient: startMock.savedObjects.client,
indexPatterns: indexPatternsMock,
application: startMock.application,
});
indexPatternsMock = ({
get: jest.fn(),
Expand Down Expand Up @@ -232,13 +237,16 @@ describe('connect_to_global_state', () => {
queryService.setup({
uiSettings: setupMock.uiSettings,
storage: new DataStorage(window.localStorage, 'opensearch_dashboards.'),
sessionStorage: new DataStorage(window.sessionStorage, 'opensearch_dashboards.'),
defaultSearchInterceptor: mockSearchInterceptor,
application: setupMock.application,
});
queryServiceStart = queryService.start({
uiSettings: setupMock.uiSettings,
storage: new DataStorage(window.localStorage, 'opensearch_dashboards.'),
savedObjectsClient: startMock.savedObjects.client,
indexPatterns: indexPatternsMock,
application: startMock.application,
});
filterManager = queryServiceStart.filterManager;
timeFilter = queryServiceStart.timefilter.timefilter;
Expand Down Expand Up @@ -473,13 +481,16 @@ describe('connect_to_app_state', () => {
queryService.setup({
uiSettings: setupMock.uiSettings,
storage: new DataStorage(window.localStorage, 'opensearch_dashboards.'),
sessionStorage: new DataStorage(window.sessionStorage, 'opensearch_dashboards.'),
defaultSearchInterceptor: mockSearchInterceptor,
application: setupMock.application,
});
queryServiceStart = queryService.start({
uiSettings: setupMock.uiSettings,
storage: new DataStorage(window.localStorage, 'opensearch_dashboards.'),
savedObjectsClient: startMock.savedObjects.client,
indexPatterns: indexPatternsMock,
application: startMock.application,
});
filterManager = queryServiceStart.filterManager;
indexPatternsMock = ({
Expand Down Expand Up @@ -659,13 +670,16 @@ describe('filters with different state', () => {
queryService.setup({
uiSettings: setupMock.uiSettings,
storage: new DataStorage(window.localStorage, 'opensearch_dashboards.'),
sessionStorage: new DataStorage(window.sessionStorage, 'opensearch_dashboards.'),
defaultSearchInterceptor: mockSearchInterceptor,
application: setupMock.application,
});
queryServiceStart = queryService.start({
uiSettings: setupMock.uiSettings,
storage: new DataStorage(window.localStorage, 'opensearch_dashboards.'),
savedObjectsClient: startMock.savedObjects.client,
indexPatterns: indexPatternsMock,
application: startMock.application,
});
filterManager = queryServiceStart.filterManager;
indexPatternsMock = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { QueryService, QueryStart } from '../query_service';
import { TimefilterContract } from '../timefilter';
import { syncQueryStateWithUrl } from './sync_state_with_url';
import { QueryState } from './types';
import { ISearchInterceptor } from '../../search';

const setupMock = coreMock.createSetup();
const startMock = coreMock.createStart();
Expand All @@ -66,6 +67,8 @@ setupMock.uiSettings.get.mockImplementation((key: string) => {
return { pause: false, value: 0 };
case UI_SETTINGS.QUERY_ENHANCEMENTS_ENABLED:
return false;
case UI_SETTINGS.SEARCH_MAX_RECENT_DATASETS:
return 4;
default:
throw new Error(`sync_query test: not mocked uiSetting: ${key}`);
}
Expand All @@ -87,6 +90,7 @@ describe('sync_query_state_with_url', () => {

let filterManagerChangeSub: Subscription;
let filterManagerChangeTriggered = jest.fn();
let mockSearchInterceptor: jest.Mocked<ISearchInterceptor>;

let gF: Filter;
let aF: Filter;
Expand All @@ -99,12 +103,16 @@ describe('sync_query_state_with_url', () => {
queryService.setup({
uiSettings: setupMock.uiSettings,
storage: new DataStorage(window.localStorage, 'opensearch_dashboards.'),
sessionStorage: new DataStorage(window.sessionStorage, 'opensearch_dashboards.'),
defaultSearchInterceptor: mockSearchInterceptor,
application: setupMock.application,
});
queryServiceStart = queryService.start({
indexPatterns: indexPatternsMock,
uiSettings: startMock.uiSettings,
storage: new DataStorage(window.localStorage, 'opensearch_dashboards.'),
savedObjectsClient: startMock.savedObjects.client,
application: startMock.application,
});
filterManager = queryServiceStart.filterManager;
timefilter = queryServiceStart.timefilter.timefilter;
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data/public/query/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export interface QueryServiceSetupDependencies {
storage: DataStorage;
sessionStorage: DataStorage;
defaultSearchInterceptor: ISearchInterceptor;
applicaton: ApplicationSetup;
application: ApplicationSetup;
}

/** @internal */
Expand All @@ -52,5 +52,5 @@ export interface QueryServiceStartDependencies {
storage: DataStorage;
uiSettings: IUiSettingsClient;
indexPatterns: IndexPatternsService;
applicaton: ApplicationStart;
application: ApplicationStart;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jest.mock('../../services', () => ({
describe('DatasetSelector', () => {
const nextTick = () => new Promise((res) => process.nextTick(res));

const fetchMock = jest.fn().mockResolvedValue({ children: [] });
const fetchMock = jest.fn().mockResolvedValue([]);
const setDatasetsMock = jest.fn();
const mockDatasetTypeConfig: DatasetTypeConfig = {
id: 'mockType',
Expand Down Expand Up @@ -56,6 +56,8 @@ describe('DatasetSelector', () => {
queryString: {
getDatasetService: jest.fn().mockReturnValue({
getType: getTypeMock,
getRecentDatasets: jest.fn().mockReturnValue([]),
addRecentDataset: jest.fn(),
}),
},
});
Expand Down
Loading

0 comments on commit 2833351

Please sign in to comment.