From 15878e30462fde9c14e0b818f0e3dbb49e5251b0 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 18 Oct 2022 16:45:01 -0400 Subject: [PATCH 01/23] Create filter registry for saved object management to make filters extensible Signed-off-by: Craig Perkins --- .../saved_objects_management/public/index.ts | 3 ++ .../management_section/mount_section.tsx | 1 + .../objects_table/components/table.tsx | 9 ++++ .../objects_table/saved_objects_table.tsx | 3 ++ .../saved_objects_table_page.tsx | 3 ++ .../saved_objects_management/public/plugin.ts | 10 ++++ .../public/services/filter_service.ts | 47 +++++++++++++++++++ .../public/services/index.ts | 6 +++ .../public/services/types/filter.ts | 25 ++++++++++ 9 files changed, 107 insertions(+) create mode 100644 src/plugins/saved_objects_management/public/services/filter_service.ts create mode 100644 src/plugins/saved_objects_management/public/services/types/filter.ts diff --git a/src/plugins/saved_objects_management/public/index.ts b/src/plugins/saved_objects_management/public/index.ts index 147247c56d77..db071d20af18 100644 --- a/src/plugins/saved_objects_management/public/index.ts +++ b/src/plugins/saved_objects_management/public/index.ts @@ -39,6 +39,9 @@ export { SavedObjectsManagementColumnServiceSetup, SavedObjectsManagementColumnServiceStart, SavedObjectsManagementColumn, + SavedObjectsManagementFilterServiceSetup, + SavedObjectsManagementFilterServiceStart, + SavedObjectsManagementFilter, SavedObjectsManagementRecord, ISavedObjectsManagementServiceRegistry, SavedObjectsManagementServiceRegistryEntry, diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx index 8013c05aad79..857228460631 100644 --- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -104,6 +104,7 @@ export const mountManagementSection = async ({ serviceRegistry={serviceRegistry} actionRegistry={pluginStart.actions} columnRegistry={pluginStart.columns} + filterRegistry={pluginStart.filters} allowedTypes={allowedObjectTypes} setBreadcrumbs={setBreadcrumbs} /> diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 50ec838b9860..aad9364fc3ca 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -55,12 +55,14 @@ import { SavedObjectsManagementActionServiceStart, SavedObjectsManagementAction, SavedObjectsManagementColumnServiceStart, + SavedObjectsManagementFilterServiceStart, } from '../../../services'; export interface TableProps { basePath: IBasePath; actionRegistry: SavedObjectsManagementActionServiceStart; columnRegistry: SavedObjectsManagementColumnServiceStart; + filterRegistry: SavedObjectsManagementFilterServiceStart; selectedSavedObjects: SavedObjectWithMetadata[]; selectionConfig: { onSelectionChange: (selection: SavedObjectWithMetadata[]) => void; @@ -174,6 +176,7 @@ export class Table extends PureComponent { basePath, actionRegistry, columnRegistry, + filterRegistry, dateFormat, } = this.props; @@ -194,6 +197,12 @@ export class Table extends PureComponent { multiSelect: 'or', options: filterOptions, }, + ...filterRegistry.getAll().map((filter) => { + return { + ...filter, + 'data-test-subj': `savedObjectsFilter-${filter.id}`, + }; + }), // Add this back in once we have tag support // { // type: 'field_value_selection', diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 8d0d13d3334a..e22ee4e570df 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -85,6 +85,7 @@ import { ISavedObjectsManagementServiceRegistry, SavedObjectsManagementActionServiceStart, SavedObjectsManagementColumnServiceStart, + SavedObjectsManagementFilterServiceStart, } from '../../services'; import { Header, Table, Flyout, Relationships } from './components'; import { DataPublicPluginStart } from '../../../../../plugins/data/public'; @@ -99,6 +100,7 @@ export interface SavedObjectsTableProps { serviceRegistry: ISavedObjectsManagementServiceRegistry; actionRegistry: SavedObjectsManagementActionServiceStart; columnRegistry: SavedObjectsManagementColumnServiceStart; + filterRegistry: SavedObjectsManagementFilterServiceStart; savedObjectsClient: SavedObjectsClientContract; indexPatterns: IndexPatternsContract; http: HttpStart; @@ -795,6 +797,7 @@ export class SavedObjectsTable extends Component void; }) => { const capabilities = coreStart.application.capabilities; @@ -78,6 +80,7 @@ const SavedObjectsTablePage = ({ serviceRegistry={serviceRegistry} actionRegistry={actionRegistry} columnRegistry={columnRegistry} + filterRegistry={filterRegistry} savedObjectsClient={coreStart.savedObjects.client} indexPatterns={dataStart.indexPatterns} search={dataStart.search} diff --git a/src/plugins/saved_objects_management/public/plugin.ts b/src/plugins/saved_objects_management/public/plugin.ts index 1ccf9772ff2c..537df8b51452 100644 --- a/src/plugins/saved_objects_management/public/plugin.ts +++ b/src/plugins/saved_objects_management/public/plugin.ts @@ -45,6 +45,9 @@ import { SavedObjectsManagementColumnService, SavedObjectsManagementColumnServiceSetup, SavedObjectsManagementColumnServiceStart, + SavedObjectsManagementFilterService, + SavedObjectsManagementFilterServiceSetup, + SavedObjectsManagementFilterServiceStart, SavedObjectsManagementServiceRegistry, ISavedObjectsManagementServiceRegistry, } from './services'; @@ -53,12 +56,14 @@ import { registerServices } from './register_services'; export interface SavedObjectsManagementPluginSetup { actions: SavedObjectsManagementActionServiceSetup; columns: SavedObjectsManagementColumnServiceSetup; + filters: SavedObjectsManagementFilterServiceSetup; serviceRegistry: ISavedObjectsManagementServiceRegistry; } export interface SavedObjectsManagementPluginStart { actions: SavedObjectsManagementActionServiceStart; columns: SavedObjectsManagementColumnServiceStart; + filters: SavedObjectsManagementFilterServiceStart; } export interface SetupDependencies { @@ -84,6 +89,7 @@ export class SavedObjectsManagementPlugin > { private actionService = new SavedObjectsManagementActionService(); private columnService = new SavedObjectsManagementColumnService(); + private filterService = new SavedObjectsManagementFilterService(); private serviceRegistry = new SavedObjectsManagementServiceRegistry(); public setup( @@ -92,6 +98,7 @@ export class SavedObjectsManagementPlugin ): SavedObjectsManagementPluginSetup { const actionSetup = this.actionService.setup(); const columnSetup = this.columnService.setup(); + const filterSetup = this.filterService.setup(); if (home) { home.featureCatalogue.register({ @@ -133,6 +140,7 @@ export class SavedObjectsManagementPlugin return { actions: actionSetup, columns: columnSetup, + filters: filterSetup, serviceRegistry: this.serviceRegistry, }; } @@ -140,10 +148,12 @@ export class SavedObjectsManagementPlugin public start(core: CoreStart, { data }: StartDependencies) { const actionStart = this.actionService.start(); const columnStart = this.columnService.start(); + const filterStart = this.filterService.start(); return { actions: actionStart, columns: columnStart, + filters: filterStart, }; } } diff --git a/src/plugins/saved_objects_management/public/services/filter_service.ts b/src/plugins/saved_objects_management/public/services/filter_service.ts new file mode 100644 index 000000000000..2c903a1d335e --- /dev/null +++ b/src/plugins/saved_objects_management/public/services/filter_service.ts @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +import { SavedObjectsManagementFilter } from './types'; + +export interface SavedObjectsManagementFilterServiceSetup { + /** + * register given filter in the registry. + */ + register: (filter: SavedObjectsManagementFilter) => void; +} + +export interface SavedObjectsManagementFilterServiceStart { + /** + * return all {@link SavedObjectsManagementFilter | filters} currently registered. + */ + getAll: () => Array>; +} + +export class SavedObjectsManagementFilterService { + private readonly filters = new Map>(); + + setup(): SavedObjectsManagementFilterServiceSetup { + return { + register: (filter) => { + if (this.filters.has(filter.id)) { + throw new Error(`Saved Objects Management Filter with id '${filter.id}' already exists`); + } + this.filters.set(filter.id, filter); + }, + }; + } + + start(): SavedObjectsManagementFilterServiceStart { + return { + getAll: () => [...this.filters.values()], + }; + } +} diff --git a/src/plugins/saved_objects_management/public/services/index.ts b/src/plugins/saved_objects_management/public/services/index.ts index 7d099852776d..9a23058d148e 100644 --- a/src/plugins/saved_objects_management/public/services/index.ts +++ b/src/plugins/saved_objects_management/public/services/index.ts @@ -38,6 +38,11 @@ export { SavedObjectsManagementColumnServiceStart, SavedObjectsManagementColumnServiceSetup, } from './column_service'; +export { + SavedObjectsManagementFilterService, + SavedObjectsManagementFilterServiceStart, + SavedObjectsManagementFilterServiceSetup, +} from './filter_service'; export { SavedObjectsManagementServiceRegistry, ISavedObjectsManagementServiceRegistry, @@ -46,5 +51,6 @@ export { export { SavedObjectsManagementAction, SavedObjectsManagementColumn, + SavedObjectsManagementFilter, SavedObjectsManagementRecord, } from './types'; diff --git a/src/plugins/saved_objects_management/public/services/types/filter.ts b/src/plugins/saved_objects_management/public/services/types/filter.ts new file mode 100644 index 000000000000..7e737c00dbfa --- /dev/null +++ b/src/plugins/saved_objects_management/public/services/types/filter.ts @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +interface SavedObjectsManagementFilterOption { + value: string; + name: string; + view: string; +} + +export interface SavedObjectsManagementFilter { + id: string; + type: string; + field: string; + name: string; + multiSelect: string; + options: SavedObjectsManagementFilterOption; +} From e61d803898631095b913a72636dd280beb57a8c0 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 19 Oct 2022 11:36:17 -0400 Subject: [PATCH 02/23] WIP on making fetchCounts generic Signed-off-by: Craig Perkins --- .../public/lib/parse_query.ts | 16 +++++--- .../objects_table/components/table.tsx | 34 ++--------------- .../objects_table/saved_objects_table.tsx | 37 ++++++++++++++++--- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/plugins/saved_objects_management/public/lib/parse_query.ts b/src/plugins/saved_objects_management/public/lib/parse_query.ts index dca6384efbe1..dabeb7126f13 100644 --- a/src/plugins/saved_objects_management/public/lib/parse_query.ts +++ b/src/plugins/saved_objects_management/public/lib/parse_query.ts @@ -32,12 +32,12 @@ import { Query } from '@elastic/eui'; interface ParsedQuery { queryText?: string; - visibleTypes?: string[]; + parsedParams?: any; } -export function parseQuery(query: Query): ParsedQuery { +export function parseQuery(query: Query, filterFields: string[]): ParsedQuery { let queryText: string | undefined; - let visibleTypes: string[] | undefined; + const parsedParams: any = {}; if (query) { if (query.ast.getTermClauses().length) { @@ -46,13 +46,17 @@ export function parseQuery(query: Query): ParsedQuery { .map((clause: any) => clause.value) .join(' '); } - if (query.ast.getFieldClauses('type')) { - visibleTypes = query.ast.getFieldClauses('type')[0].value as string[]; + if (!!filterFields) { + filterFields.forEach((field) => { + if (query.ast.getFieldClauses(field)) { + parsedParams[field] = query.ast.getFieldClauses(field)[0].value as string[]; + } + }); } } return { queryText, - visibleTypes, + parsedParams, }; } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index aad9364fc3ca..32b4395dc5f1 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -62,12 +62,11 @@ export interface TableProps { basePath: IBasePath; actionRegistry: SavedObjectsManagementActionServiceStart; columnRegistry: SavedObjectsManagementColumnServiceStart; - filterRegistry: SavedObjectsManagementFilterServiceStart; + filters: SavedObjectsManagementFilter[]; selectedSavedObjects: SavedObjectWithMetadata[]; selectionConfig: { onSelectionChange: (selection: SavedObjectWithMetadata[]) => void; }; - filterOptions: any[]; canDelete: boolean; onDelete: () => void; onActionRefresh: (object: SavedObjectWithMetadata) => void; @@ -78,7 +77,7 @@ export interface TableProps { items: SavedObjectWithMetadata[]; itemId: string | (() => string); totalItemCount: number; - onQueryChange: (query: any) => void; + onQueryChange: (query: any, filterFields: string[]) => void; onTableChange: (table: any) => void; isSearching: boolean; onShowRelationships: (object: SavedObjectWithMetadata) => void; @@ -165,7 +164,6 @@ export class Table extends PureComponent { items, totalItemCount, isSearching, - filterOptions, selectionConfig: selection, onDelete, onActionRefresh, @@ -176,7 +174,7 @@ export class Table extends PureComponent { basePath, actionRegistry, columnRegistry, - filterRegistry, + filters, dateFormat, } = this.props; @@ -187,32 +185,6 @@ export class Table extends PureComponent { pageSizeOptions: [5, 10, 20, 50], }; - const filters = [ - { - type: 'field_value_selection', - field: 'type', - name: i18n.translate('savedObjectsManagement.objectsTable.table.typeFilterName', { - defaultMessage: 'Type', - }), - multiSelect: 'or', - options: filterOptions, - }, - ...filterRegistry.getAll().map((filter) => { - return { - ...filter, - 'data-test-subj': `savedObjectsFilter-${filter.id}`, - }; - }), - // Add this back in once we have tag support - // { - // type: 'field_value_selection', - // field: 'tag', - // name: 'Tags', - // multiSelect: 'or', - // options: [], - // }, - ]; - const columns = [ { field: 'type', diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index e22ee4e570df..de308cbd0f00 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -178,9 +178,11 @@ export class SavedObjectsTable extends Component { - const { allowedTypes } = this.props; - const { queryText, visibleTypes } = parseQuery(this.state.activeQuery); + const { allowedTypes, filterRegistry } = this.props; + const filterFields = ['type', ...filterRegistry.getAll().map((f) => f.field)]; + const { queryText, parsedParams } = parseQuery(this.state.activeQuery, filterFields); + const visibleTypes = parsedParams.type || []; const filteredTypes = allowedTypes.filter( (type) => !visibleTypes || visibleTypes.includes(type) ); @@ -766,7 +768,7 @@ export class SavedObjectsTable extends Component { + return { + ...filter, + 'data-test-subj': `savedObjectsFilter-${filter.id}`, + }; + }), + // Add this back in once we have tag support + // { + // type: 'field_value_selection', + // field: 'tag', + // name: 'Tags', + // multiSelect: 'or', + // options: [], + // }, + ]; + return ( {this.renderFlyout()} @@ -797,12 +825,11 @@ export class SavedObjectsTable extends Component Date: Wed, 19 Oct 2022 12:20:40 -0400 Subject: [PATCH 03/23] First step at making scroll_counts generic Signed-off-by: Craig Perkins --- .../public/lib/get_saved_object_counts.ts | 4 ++-- .../objects_table/saved_objects_table.tsx | 5 +++-- .../server/routes/scroll_count.ts | 11 ++++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts b/src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts index 0dbf71f8e8c0..dd173c8f29dc 100644 --- a/src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts +++ b/src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts @@ -32,11 +32,11 @@ import { HttpStart } from 'src/core/public'; export async function getSavedObjectCounts( http: HttpStart, - typesToInclude: string[], + params: any, searchString?: string ): Promise> { return await http.post>( `/api/opensearch-dashboards/management/saved_objects/scroll/counts`, - { body: JSON.stringify({ typesToInclude, searchString }) } + { body: JSON.stringify({ params, searchString }) } ); } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index de308cbd0f00..31c603ab3d5c 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -190,7 +190,7 @@ export class SavedObjectsTable extends Component ({ ...state, diff --git a/src/plugins/saved_objects_management/server/routes/scroll_count.ts b/src/plugins/saved_objects_management/server/routes/scroll_count.ts index 0c69b376ea5b..63c3866673d7 100644 --- a/src/plugins/saved_objects_management/server/routes/scroll_count.ts +++ b/src/plugins/saved_objects_management/server/routes/scroll_count.ts @@ -38,7 +38,10 @@ export const registerScrollForCountRoute = (router: IRouter) => { path: '/api/opensearch-dashboards/management/saved_objects/scroll/counts', validate: { body: schema.object({ - typesToInclude: schema.arrayOf(schema.string()), + params: schema.object({ + type: schema.maybe(schema.arrayOf(schema.string())), + namespaces: schema.maybe(schema.arrayOf(schema.string())), + }), searchString: schema.maybe(schema.string()), }), }, @@ -47,9 +50,11 @@ export const registerScrollForCountRoute = (router: IRouter) => { const { client } = context.core.savedObjects; const findOptions: SavedObjectsFindOptions = { - type: req.body.typesToInclude, + ...req.body.params, + type: req.body.params.type || [], perPage: 1000, }; + if (req.body.searchString) { findOptions.search = `${req.body.searchString}*`; findOptions.searchFields = ['title']; @@ -64,7 +69,7 @@ export const registerScrollForCountRoute = (router: IRouter) => { return accum; }, {} as Record); - for (const type of req.body.typesToInclude) { + for (const type of findOptions.type) { if (!counts[type]) { counts[type] = 0; } From bc6158cabdcb531c53679280d7d9a65d63765ca8 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 19 Oct 2022 16:33:50 -0400 Subject: [PATCH 04/23] Work on getting other filter counts with same object count endpoint Signed-off-by: Craig Perkins --- .../public/lib/get_saved_object_counts.ts | 5 +-- .../objects_table/saved_objects_table.tsx | 33 +++++++++++------ .../server/routes/find.ts | 1 + .../server/routes/scroll_count.ts | 35 ++++++++++++------- 4 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts b/src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts index dd173c8f29dc..bdfab075db80 100644 --- a/src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts +++ b/src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts @@ -32,11 +32,12 @@ import { HttpStart } from 'src/core/public'; export async function getSavedObjectCounts( http: HttpStart, - params: any, + typesToInclude: string[], + namespacesToInclude: string[], searchString?: string ): Promise> { return await http.post>( `/api/opensearch-dashboards/management/saved_objects/scroll/counts`, - { body: JSON.stringify({ params, searchString }) } + { body: JSON.stringify({ typesToInclude, namespacesToInclude, searchString }) } ); } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 31c603ab3d5c..bb90309972f2 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -181,8 +181,8 @@ export class SavedObjectsTable extends Component f.field)]; const { queryText, parsedParams } = parseQuery(this.state.activeQuery, filterFields); + const { type: visibleTypes, namespaces } = parsedParams; - const visibleTypes = parsedParams.type || []; const filteredTypes = allowedTypes.filter( (type) => !visibleTypes || visibleTypes.includes(type) ); @@ -190,7 +190,8 @@ export class SavedObjectsTable extends Component ({ ...state, @@ -231,8 +236,13 @@ export class SavedObjectsTable extends Component { const { activeQuery: query, page, perPage } = this.state; - const { notifications, http, allowedTypes } = this.props; - const { queryText, visibleTypes } = parseQuery(query); + const { notifications, http, allowedTypes, filterRegistry } = this.props; + const filterFields = ['type', ...filterRegistry.getAll().map((f) => f.field)]; + const { queryText, parsedParams } = parseQuery(query, filterFields); + const { type: visibleTypes, namespaces } = parsedParams; + const filteredTypes = allowedTypes.filter( + (type) => !visibleTypes || visibleTypes.includes(type) + ); // "searchFields" is missing from the "findOptions" but gets injected via the API. // The API extracts the fields from each uiExports.savedObjectsManagement "defaultSearchField" attribute const findOptions: SavedObjectsFindOptions = { @@ -240,7 +250,8 @@ export class SavedObjectsTable extends Component !visibleTypes || visibleTypes.includes(type)), + type: filteredTypes, + namespaces, }; if (findOptions.type.length > 1) { findOptions.sortField = 'type'; @@ -394,8 +405,9 @@ export class SavedObjectsTable extends Component { const { exportAllSelectedOptions, isIncludeReferencesDeepChecked, activeQuery } = this.state; - const { notifications, http } = this.props; - const { queryText } = parseQuery(activeQuery); + const { notifications, http, filterRegistry } = this.props; + + const { queryText } = parseQuery(activeQuery, filterFields); const exportTypes = Object.entries(exportAllSelectedOptions).reduce((accum, [id, selected]) => { if (selected) { accum.push(id); @@ -774,11 +786,12 @@ export class SavedObjectsTable extends Component ({ value: type, name: type, - view: `${type} (${savedObjectCounts[type] || 0})`, + view: `${type} (${typeCounts[type] || 0})`, })); const filters = [ diff --git a/src/plugins/saved_objects_management/server/routes/find.ts b/src/plugins/saved_objects_management/server/routes/find.ts index 2987425321ca..c1bb6ff7a7a9 100644 --- a/src/plugins/saved_objects_management/server/routes/find.ts +++ b/src/plugins/saved_objects_management/server/routes/find.ts @@ -45,6 +45,7 @@ export const registerFindRoute = ( perPage: schema.number({ min: 0, defaultValue: 20 }), page: schema.number({ min: 0, defaultValue: 1 }), type: schema.oneOf([schema.string(), schema.arrayOf(schema.string())]), + namespaces: schema.maybe(schema.arrayOf(schema.string())), search: schema.maybe(schema.string()), defaultSearchOperator: schema.oneOf([schema.literal('OR'), schema.literal('AND')], { defaultValue: 'OR', diff --git a/src/plugins/saved_objects_management/server/routes/scroll_count.ts b/src/plugins/saved_objects_management/server/routes/scroll_count.ts index 63c3866673d7..92d85b97797f 100644 --- a/src/plugins/saved_objects_management/server/routes/scroll_count.ts +++ b/src/plugins/saved_objects_management/server/routes/scroll_count.ts @@ -38,10 +38,8 @@ export const registerScrollForCountRoute = (router: IRouter) => { path: '/api/opensearch-dashboards/management/saved_objects/scroll/counts', validate: { body: schema.object({ - params: schema.object({ - type: schema.maybe(schema.arrayOf(schema.string())), - namespaces: schema.maybe(schema.arrayOf(schema.string())), - }), + typesToInclude: schema.arrayOf(schema.string()), + namespacesToInclude: schema.maybe(schema.arrayOf(schema.string())), searchString: schema.maybe(schema.string()), }), }, @@ -51,7 +49,7 @@ export const registerScrollForCountRoute = (router: IRouter) => { const findOptions: SavedObjectsFindOptions = { ...req.body.params, - type: req.body.params.type || [], + type: req.body.typesToInclude, perPage: 1000, }; @@ -62,16 +60,27 @@ export const registerScrollForCountRoute = (router: IRouter) => { const objects = await findAll(client, findOptions); - const counts = objects.reduce((accum, result) => { + const counts = { + type: {}, + namespaces: {}, + }; + + objects.forEach((result) => { const type = result.type; - accum[type] = accum[type] || 0; - accum[type]++; - return accum; - }, {} as Record); + if (req.body.namespacesToInclude) { + const namespaces = (result.namespaces || []).flat(); + namespaces.forEach((ns) => { + counts.namespaces[ns] = counts.namespaces[ns] || 0; + counts.namespaces[ns]++; + }); + } + counts.type[type] = counts.type[type] || 0; + counts.type[type]++; + }); - for (const type of findOptions.type) { - if (!counts[type]) { - counts[type] = 0; + for (const type of req.body.typesToInclude) { + if (!counts.type[type]) { + counts.type[type] = 0; } } From e3dc3b314c5198e8358c824f4b8908291832161d Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 19 Oct 2022 17:36:18 -0400 Subject: [PATCH 05/23] Get tenant count options to display Signed-off-by: Craig Perkins --- .../objects_table/saved_objects_table.tsx | 6 ++++++ .../saved_objects_management/server/routes/scroll_count.ts | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index bb90309972f2..47bba2280f82 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -805,6 +805,12 @@ export class SavedObjectsTable extends Component { + const fieldCounts = savedObjectCounts[filter.field] || {}; + if (filter.options) { + filter.options.map((filterOption) => { + filterOption.view = `${filterOption.name} (${fieldCounts[filterOption.value] || 0})`; + }); + } return { ...filter, 'data-test-subj': `savedObjectsFilter-${filter.id}`, diff --git a/src/plugins/saved_objects_management/server/routes/scroll_count.ts b/src/plugins/saved_objects_management/server/routes/scroll_count.ts index 92d85b97797f..92002f615d31 100644 --- a/src/plugins/saved_objects_management/server/routes/scroll_count.ts +++ b/src/plugins/saved_objects_management/server/routes/scroll_count.ts @@ -70,6 +70,9 @@ export const registerScrollForCountRoute = (router: IRouter) => { if (req.body.namespacesToInclude) { const namespaces = (result.namespaces || []).flat(); namespaces.forEach((ns) => { + if (ns === null || ns === '') { + ns = ''; + } counts.namespaces[ns] = counts.namespaces[ns] || 0; counts.namespaces[ns]++; }); From 445ffc7ec80b3545f33bbefebe5a14c7ca125593 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 20 Oct 2022 12:48:34 -0400 Subject: [PATCH 06/23] Extend find to work with namespaces for saved objects Signed-off-by: Craig Perkins --- .../saved_objects/serialization/serializer.ts | 2 +- .../server/routes/find.ts | 18 ++++++++++++++- .../server/routes/scroll_count.ts | 22 +++++++++++++++---- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/core/server/saved_objects/serialization/serializer.ts b/src/core/server/saved_objects/serialization/serializer.ts index ff840a1fac60..3c267b61d53d 100644 --- a/src/core/server/saved_objects/serialization/serializer.ts +++ b/src/core/server/saved_objects/serialization/serializer.ts @@ -152,7 +152,7 @@ export class SavedObjectsSerializer { namespace && this.registry.isSingleNamespace(type) ? `${namespace}:` : ''; const prefix = `${namespacePrefix}${type}:`; - if (!id.startsWith(prefix)) { + if (!id.startsWith(prefix) || type === 'config') { return id; } diff --git a/src/plugins/saved_objects_management/server/routes/find.ts b/src/plugins/saved_objects_management/server/routes/find.ts index c1bb6ff7a7a9..4324db3eedcc 100644 --- a/src/plugins/saved_objects_management/server/routes/find.ts +++ b/src/plugins/saved_objects_management/server/routes/find.ts @@ -45,7 +45,9 @@ export const registerFindRoute = ( perPage: schema.number({ min: 0, defaultValue: 20 }), page: schema.number({ min: 0, defaultValue: 1 }), type: schema.oneOf([schema.string(), schema.arrayOf(schema.string())]), - namespaces: schema.maybe(schema.arrayOf(schema.string())), + namespaces: schema.maybe( + schema.oneOf([schema.string(), schema.arrayOf(schema.string())]) + ), search: schema.maybe(schema.string()), defaultSearchOperator: schema.oneOf([schema.literal('OR'), schema.literal('AND')], { defaultValue: 'OR', @@ -67,6 +69,20 @@ export const registerFindRoute = ( const managementService = await managementServicePromise; const { client } = context.core.savedObjects; const searchTypes = Array.isArray(req.query.type) ? req.query.type : [req.query.type]; + if ('namespaces' in req.query) { + const namespacesToInclude = Array.isArray(req.query.namespaces) + ? req.query.namespaces + : [req.query.namespaces]; + const searchNamespaces = []; + namespacesToInclude.forEach((ns) => { + if (ns == null) { + searchNamespaces.push('default'); + } else { + searchNamespaces.push(ns); + } + }); + req.query.namespaces = searchNamespaces; + } const includedFields = Array.isArray(req.query.fields) ? req.query.fields : [req.query.fields]; diff --git a/src/plugins/saved_objects_management/server/routes/scroll_count.ts b/src/plugins/saved_objects_management/server/routes/scroll_count.ts index 92002f615d31..20d1aa6aea9f 100644 --- a/src/plugins/saved_objects_management/server/routes/scroll_count.ts +++ b/src/plugins/saved_objects_management/server/routes/scroll_count.ts @@ -46,6 +46,16 @@ export const registerScrollForCountRoute = (router: IRouter) => { }, router.handleLegacyErrors(async (context, req, res) => { const { client } = context.core.savedObjects; + const namespaces = []; + if (req.body.namespacesToInclude && req.body.namespacesToInclude.length > 0) { + req.body.namespacesToInclude.forEach((ns) => { + if (ns === null) { + namespaces.push('default'); + } else { + namespaces.push(ns); + } + }); + } const findOptions: SavedObjectsFindOptions = { ...req.body.params, @@ -53,6 +63,10 @@ export const registerScrollForCountRoute = (router: IRouter) => { perPage: 1000, }; + if (namespaces.length > 0) { + findOptions.namespaces = namespaces; + } + if (req.body.searchString) { findOptions.search = `${req.body.searchString}*`; findOptions.searchFields = ['title']; @@ -68,10 +82,10 @@ export const registerScrollForCountRoute = (router: IRouter) => { objects.forEach((result) => { const type = result.type; if (req.body.namespacesToInclude) { - const namespaces = (result.namespaces || []).flat(); - namespaces.forEach((ns) => { - if (ns === null || ns === '') { - ns = ''; + const resultNamespaces = (result.namespaces || []).flat(); + resultNamespaces.forEach((ns) => { + if (ns === null) { + ns = 'default'; } counts.namespaces[ns] = counts.namespaces[ns] || 0; counts.namespaces[ns]++; From f31e0efc92915897776b70e2d37e11aa37228099 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 20 Oct 2022 14:30:33 -0400 Subject: [PATCH 07/23] Add missing filterFields Signed-off-by: Craig Perkins --- .../management_section/objects_table/saved_objects_table.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 47bba2280f82..76e06e80a0dc 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -407,6 +407,7 @@ export class SavedObjectsTable extends Component f.field)]; const { queryText } = parseQuery(activeQuery, filterFields); const exportTypes = Object.entries(exportAllSelectedOptions).reduce((accum, [id, selected]) => { if (selected) { From f4d13eb32d5e92c0d80ea0f237ec428edbd2fce9 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 20 Oct 2022 16:35:07 -0400 Subject: [PATCH 08/23] Update jest tests Signed-off-by: Craig Perkins --- .../public/lib/parse_query.test.ts | 5 ++++- .../objects_table/components/table.test.tsx | 14 +++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/plugins/saved_objects_management/public/lib/parse_query.test.ts b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts index 854c1e4ea3d6..d303ccc37da7 100644 --- a/src/plugins/saved_objects_management/public/lib/parse_query.test.ts +++ b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts @@ -36,6 +36,9 @@ describe('getQueryText', () => { getTermClauses: () => [{ value: 'foo' }, { value: 'bar' }], getFieldClauses: () => [{ value: 'lala' }, { value: 'lolo' }], }; - expect(parseQuery({ ast } as any)).toEqual({ queryText: 'foo bar', visibleTypes: 'lala' }); + expect(parseQuery({ ast } as any, ['type'])).toEqual({ + queryText: 'foo bar', + parsedParams: { type: 'lala' }, + }); }); }); diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx index 8e473730615b..7e5bb318f4d0 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx @@ -62,7 +62,19 @@ const defaultProps: TableProps = { selectionConfig: { onSelectionChange: () => {}, }, - filterOptions: [{ value: 2 }], + filters: [ + { + type: 'field_value_selection', + field: 'type', + name: 'Type', + multiSelect: 'or', + options: [ + { + value: 2, + }, + ], + }, + ], onDelete: () => {}, onActionRefresh: () => {}, onExport: () => {}, From ee15b77f9bd2c66e021007b7e8cbd328771e08ff Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 20 Oct 2022 16:47:54 -0400 Subject: [PATCH 09/23] Update saved_objects_table snapshot Signed-off-by: Craig Perkins --- .../saved_objects_table.test.tsx.snap | 46 ++++++++++------- .../saved_objects_table.test.tsx | 2 + .../public/services/filter_service.mock.ts | 49 +++++++++++++++++++ 3 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 src/plugins/saved_objects_management/public/services/filter_service.mock.ts diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap index a86362994a6b..d18762f4912f 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap @@ -274,27 +274,35 @@ exports[`SavedObjectsTable should render normally 1`] = ` "has": [MockFunction], } } - filterOptions={ + filters={ Array [ Object { - "name": "index-pattern", - "value": "index-pattern", - "view": "index-pattern (0)", - }, - Object { - "name": "visualization", - "value": "visualization", - "view": "visualization (0)", - }, - Object { - "name": "dashboard", - "value": "dashboard", - "view": "dashboard (0)", - }, - Object { - "name": "search", - "value": "search", - "view": "search (0)", + "field": "type", + "multiSelect": "or", + "name": "Type", + "options": Array [ + Object { + "name": "index-pattern", + "value": "index-pattern", + "view": "index-pattern (0)", + }, + Object { + "name": "visualization", + "value": "visualization", + "view": "visualization (0)", + }, + Object { + "name": "dashboard", + "value": "dashboard", + "view": "dashboard (0)", + }, + Object { + "name": "search", + "value": "search", + "view": "search (0)", + }, + ], + "type": "field_value_selection", }, ] } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index 2f8382c5946f..42a48732911f 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -53,6 +53,7 @@ import { dataPluginMock } from '../../../../data/public/mocks'; import { serviceRegistryMock } from '../../services/service_registry.mock'; import { actionServiceMock } from '../../services/action_service.mock'; import { columnServiceMock } from '../../services/column_service.mock'; +import { filterServiceMock } from '../../services/filter_service.mock'; import { SavedObjectsTable, SavedObjectsTableProps, @@ -147,6 +148,7 @@ describe('SavedObjectsTable', () => { serviceRegistry: serviceRegistryMock.create(), actionRegistry: actionServiceMock.createStart(), columnRegistry: columnServiceMock.createStart(), + filterRegistry: filterServiceMock.createStart(), savedObjectsClient: savedObjects.client, indexPatterns: dataPluginMock.createStartContract().indexPatterns, http, diff --git a/src/plugins/saved_objects_management/public/services/filter_service.mock.ts b/src/plugins/saved_objects_management/public/services/filter_service.mock.ts new file mode 100644 index 000000000000..73dd33fee2d6 --- /dev/null +++ b/src/plugins/saved_objects_management/public/services/filter_service.mock.ts @@ -0,0 +1,49 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +import { + SavedObjectsManagementFilterService, + SavedObjectsManagementFilterServiceSetup, + SavedObjectsManagementFilterServiceStart, +} from './filter_service'; + +const createSetupMock = (): jest.Mocked => { + const mock = { + register: jest.fn(), + }; + return mock; +}; + +const createStartMock = (): jest.Mocked => { + const mock = { + has: jest.fn(), + getAll: jest.fn(), + }; + + mock.has.mockReturnValue(true); + mock.getAll.mockReturnValue([]); + + return mock; +}; + +const createServiceMock = (): jest.Mocked> => { + const mock = { + setup: jest.fn().mockReturnValue(createSetupMock()), + start: jest.fn().mockReturnValue(createStartMock()), + }; + return mock; +}; + +export const filterServiceMock = { + create: createServiceMock, + createSetup: createSetupMock, + createStart: createStartMock, +}; From 2141b3339602ccec347826067d687688d4becbbf Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 21 Oct 2022 09:59:26 -0400 Subject: [PATCH 10/23] Append index to id to make unique Signed-off-by: Craig Perkins --- src/core/server/saved_objects/serialization/serializer.ts | 2 +- .../management_section/objects_table/components/table.tsx | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/server/saved_objects/serialization/serializer.ts b/src/core/server/saved_objects/serialization/serializer.ts index 3c267b61d53d..ff840a1fac60 100644 --- a/src/core/server/saved_objects/serialization/serializer.ts +++ b/src/core/server/saved_objects/serialization/serializer.ts @@ -152,7 +152,7 @@ export class SavedObjectsSerializer { namespace && this.registry.isSingleNamespace(type) ? `${namespace}:` : ''; const prefix = `${namespacePrefix}${type}:`; - if (!id.startsWith(prefix) || type === 'config') { + if (!id.startsWith(prefix)) { return id; } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 32b4395dc5f1..9b1950d369c9 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -350,6 +350,10 @@ export class Table extends PureComponent { const activeActionContents = this.state.activeAction?.render() ?? null; + items.forEach((item, idx) => { + item.id = `${item.id}-${idx}` + }); + return ( {activeActionContents} From 51b1325874d436d9e8dafd14a3c0f7dea4917a77 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 21 Oct 2022 10:42:03 -0400 Subject: [PATCH 11/23] Add semi-colon Signed-off-by: Craig Perkins --- .../management_section/objects_table/components/table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 9b1950d369c9..6c5e2cf61f6b 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -351,7 +351,7 @@ export class Table extends PureComponent { const activeActionContents = this.state.activeAction?.render() ?? null; items.forEach((item, idx) => { - item.id = `${item.id}-${idx}` + item.id = `${item.id}-${idx}`; }); return ( From c2ceffe152ae166cfd58fe36ef6feaf800f23a7e Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 21 Oct 2022 11:44:52 -0400 Subject: [PATCH 12/23] Fix saved objects table tests with new id scheme Signed-off-by: Craig Perkins --- .../components/__snapshots__/table.test.tsx.snap | 4 ++-- .../management_section/objects_table/components/table.tsx | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap index e22f7f3a0128..3988f14cab24 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap @@ -182,7 +182,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` Array [ Object { "attributes": Object {}, - "id": "1", + "id": "1-0", "meta": Object { "editUrl": "#/management/opensearch-dashboards/indexPatterns/patterns/1", "icon": "indexPatternApp", @@ -407,7 +407,7 @@ exports[`Table should render normally 1`] = ` Array [ Object { "attributes": Object {}, - "id": "1", + "id": "1-0", "meta": Object { "editUrl": "#/management/opensearch-dashboards/indexPatterns/patterns/1", "icon": "indexPatternApp", diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 6c5e2cf61f6b..87c7d87b1de5 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -31,6 +31,7 @@ import { IBasePath } from 'src/core/public'; import React, { PureComponent, Fragment } from 'react'; import moment from 'moment'; +import _ from 'lodash'; import { EuiSearchBar, EuiBasicTable, @@ -350,7 +351,8 @@ export class Table extends PureComponent { const activeActionContents = this.state.activeAction?.render() ?? null; - items.forEach((item, idx) => { + const itemsClone = _.cloneDeep(items); + itemsClone.forEach((item, idx) => { item.id = `${item.id}-${idx}`; }); @@ -425,7 +427,7 @@ export class Table extends PureComponent { Date: Fri, 21 Oct 2022 14:02:10 -0400 Subject: [PATCH 13/23] Only append idx on config type to ensure Advanced Settings have a unique id across tenants Signed-off-by: Craig Perkins --- .../management_section/objects_table/components/table.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 87c7d87b1de5..52bd62265ed1 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -353,7 +353,9 @@ export class Table extends PureComponent { const itemsClone = _.cloneDeep(items); itemsClone.forEach((item, idx) => { - item.id = `${item.id}-${idx}`; + if (item.type === 'config') { + item.id = `${item.id}-${idx}`; + } }); return ( From 2d976457c9c450ce7368c57df9bb07ce198ce99b Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 21 Oct 2022 15:09:59 -0400 Subject: [PATCH 14/23] Remove itemsClone in favor of showing only Advanced Settings of current tenant Signed-off-by: Craig Perkins --- .../objects_table/components/table.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 52bd62265ed1..32b4395dc5f1 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -31,7 +31,6 @@ import { IBasePath } from 'src/core/public'; import React, { PureComponent, Fragment } from 'react'; import moment from 'moment'; -import _ from 'lodash'; import { EuiSearchBar, EuiBasicTable, @@ -351,13 +350,6 @@ export class Table extends PureComponent { const activeActionContents = this.state.activeAction?.render() ?? null; - const itemsClone = _.cloneDeep(items); - itemsClone.forEach((item, idx) => { - if (item.type === 'config') { - item.id = `${item.id}-${idx}`; - } - }); - return ( {activeActionContents} @@ -429,7 +421,7 @@ export class Table extends PureComponent { Date: Mon, 24 Oct 2022 10:23:06 -0400 Subject: [PATCH 15/23] Revert snapshots in table.test.tsx Signed-off-by: Craig Perkins --- .../components/__snapshots__/table.test.tsx.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap index 3988f14cab24..e22f7f3a0128 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap @@ -182,7 +182,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` Array [ Object { "attributes": Object {}, - "id": "1-0", + "id": "1", "meta": Object { "editUrl": "#/management/opensearch-dashboards/indexPatterns/patterns/1", "icon": "indexPatternApp", @@ -407,7 +407,7 @@ exports[`Table should render normally 1`] = ` Array [ Object { "attributes": Object {}, - "id": "1-0", + "id": "1", "meta": Object { "editUrl": "#/management/opensearch-dashboards/indexPatterns/patterns/1", "icon": "indexPatternApp", From b8055314da60f3f502f29f2936fef6e3bc9db642 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 24 Oct 2022 12:18:21 -0400 Subject: [PATCH 16/23] Add additional parse_query test Signed-off-by: Craig Perkins --- .../public/lib/parse_query.test.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/plugins/saved_objects_management/public/lib/parse_query.test.ts b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts index d303ccc37da7..601eb7a1ce98 100644 --- a/src/plugins/saved_objects_management/public/lib/parse_query.test.ts +++ b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts @@ -34,11 +34,23 @@ describe('getQueryText', () => { it('should know how to get the text out of the AST', () => { const ast = { getTermClauses: () => [{ value: 'foo' }, { value: 'bar' }], - getFieldClauses: () => [{ value: 'lala' }, { value: 'lolo' }], + getFieldClauses: (field) => { + if (field === 'type') { + return [{ value: 'lala' }, { value: 'lolo' }]; + } else if (field === 'namespaces') { + return [{ value: 'default' }]; + } + return []; + } }; expect(parseQuery({ ast } as any, ['type'])).toEqual({ queryText: 'foo bar', parsedParams: { type: 'lala' }, }); + + expect(parseQuery({ ast } as any, ['namespaces'])).toEqual({ + queryText: 'foo bar', + parsedParams: { namespaces: 'default' }, + }); }); }); From 9a153ea5dbfe5cd70db89ce702d72a6e25805687 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 24 Oct 2022 12:44:05 -0400 Subject: [PATCH 17/23] Add comma Signed-off-by: Craig Perkins --- .../saved_objects_management/public/lib/parse_query.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/saved_objects_management/public/lib/parse_query.test.ts b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts index 601eb7a1ce98..b4f3d1f10307 100644 --- a/src/plugins/saved_objects_management/public/lib/parse_query.test.ts +++ b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts @@ -41,7 +41,7 @@ describe('getQueryText', () => { return [{ value: 'default' }]; } return []; - } + }, }; expect(parseQuery({ ast } as any, ['type'])).toEqual({ queryText: 'foo bar', From 8211f5e91cf9e50add999c4e5408626352249eae Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 26 Oct 2022 12:48:27 -0400 Subject: [PATCH 18/23] Create namespaceRegistry to decouple security dashboards plugin and osd core Signed-off-by: Craig Perkins --- .../saved_objects_management/public/index.ts | 6 +-- .../management_section/mount_section.tsx | 2 +- .../objects_table/components/table.tsx | 7 +-- .../saved_objects_table.test.tsx | 4 +- .../objects_table/saved_objects_table.tsx | 54 +++++++++++-------- .../saved_objects_table_page.tsx | 6 +-- .../saved_objects_management/public/plugin.ts | 20 +++---- .../public/services/filter_service.ts | 47 ---------------- .../public/services/index.ts | 10 ++-- ...vice.mock.ts => namespace_service.mock.ts} | 18 ++++--- .../public/services/namespace_service.ts | 47 ++++++++++++++++ .../types/{filter.ts => namespace.ts} | 12 +---- 12 files changed, 118 insertions(+), 115 deletions(-) delete mode 100644 src/plugins/saved_objects_management/public/services/filter_service.ts rename src/plugins/saved_objects_management/public/services/{filter_service.mock.ts => namespace_service.mock.ts} (61%) create mode 100644 src/plugins/saved_objects_management/public/services/namespace_service.ts rename src/plugins/saved_objects_management/public/services/types/{filter.ts => namespace.ts} (56%) diff --git a/src/plugins/saved_objects_management/public/index.ts b/src/plugins/saved_objects_management/public/index.ts index db071d20af18..2377afe175c4 100644 --- a/src/plugins/saved_objects_management/public/index.ts +++ b/src/plugins/saved_objects_management/public/index.ts @@ -39,9 +39,9 @@ export { SavedObjectsManagementColumnServiceSetup, SavedObjectsManagementColumnServiceStart, SavedObjectsManagementColumn, - SavedObjectsManagementFilterServiceSetup, - SavedObjectsManagementFilterServiceStart, - SavedObjectsManagementFilter, + SavedObjectsManagementNamespaceServiceSetup, + SavedObjectsManagementNamespaceServiceStart, + SavedObjectsManagementNamespace, SavedObjectsManagementRecord, ISavedObjectsManagementServiceRegistry, SavedObjectsManagementServiceRegistryEntry, diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx index 857228460631..2c42df5c7824 100644 --- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -104,7 +104,7 @@ export const mountManagementSection = async ({ serviceRegistry={serviceRegistry} actionRegistry={pluginStart.actions} columnRegistry={pluginStart.columns} - filterRegistry={pluginStart.filters} + namespaceRegistry={pluginStart.namespaces} allowedTypes={allowedObjectTypes} setBreadcrumbs={setBreadcrumbs} /> diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 32b4395dc5f1..636933d449df 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -55,18 +55,18 @@ import { SavedObjectsManagementActionServiceStart, SavedObjectsManagementAction, SavedObjectsManagementColumnServiceStart, - SavedObjectsManagementFilterServiceStart, } from '../../../services'; export interface TableProps { basePath: IBasePath; actionRegistry: SavedObjectsManagementActionServiceStart; columnRegistry: SavedObjectsManagementColumnServiceStart; - filters: SavedObjectsManagementFilter[]; + namespaceRegistry: SavedObjectsManagementNamespaceServiceStart; selectedSavedObjects: SavedObjectWithMetadata[]; selectionConfig: { onSelectionChange: (selection: SavedObjectWithMetadata[]) => void; }; + filters: any[]; canDelete: boolean; onDelete: () => void; onActionRefresh: (object: SavedObjectWithMetadata) => void; @@ -164,6 +164,7 @@ export class Table extends PureComponent { items, totalItemCount, isSearching, + filters, selectionConfig: selection, onDelete, onActionRefresh, @@ -174,7 +175,7 @@ export class Table extends PureComponent { basePath, actionRegistry, columnRegistry, - filters, + namespaceRegistry, dateFormat, } = this.props; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index 42a48732911f..e3c511bb33de 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -53,7 +53,7 @@ import { dataPluginMock } from '../../../../data/public/mocks'; import { serviceRegistryMock } from '../../services/service_registry.mock'; import { actionServiceMock } from '../../services/action_service.mock'; import { columnServiceMock } from '../../services/column_service.mock'; -import { filterServiceMock } from '../../services/filter_service.mock'; +import { namespaceServiceMock } from '../../services/namespace_service.mock'; import { SavedObjectsTable, SavedObjectsTableProps, @@ -148,7 +148,7 @@ describe('SavedObjectsTable', () => { serviceRegistry: serviceRegistryMock.create(), actionRegistry: actionServiceMock.createStart(), columnRegistry: columnServiceMock.createStart(), - filterRegistry: filterServiceMock.createStart(), + namespaceRegistry: namespaceServiceMock.createStart(), savedObjectsClient: savedObjects.client, indexPatterns: dataPluginMock.createStartContract().indexPatterns, http, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 76e06e80a0dc..a880c02c17cc 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -85,7 +85,7 @@ import { ISavedObjectsManagementServiceRegistry, SavedObjectsManagementActionServiceStart, SavedObjectsManagementColumnServiceStart, - SavedObjectsManagementFilterServiceStart, + SavedObjectsManagementNamespaceServiceStart, } from '../../services'; import { Header, Table, Flyout, Relationships } from './components'; import { DataPublicPluginStart } from '../../../../../plugins/data/public'; @@ -100,7 +100,7 @@ export interface SavedObjectsTableProps { serviceRegistry: ISavedObjectsManagementServiceRegistry; actionRegistry: SavedObjectsManagementActionServiceStart; columnRegistry: SavedObjectsManagementColumnServiceStart; - filterRegistry: SavedObjectsManagementFilterServiceStart; + namespaceRegistry: SavedObjectsManagementNamespaceServiceStart; savedObjectsClient: SavedObjectsClientContract; indexPatterns: IndexPatternsContract; http: HttpStart; @@ -178,8 +178,8 @@ export class SavedObjectsTable extends Component { - const { allowedTypes, filterRegistry } = this.props; - const filterFields = ['type', ...filterRegistry.getAll().map((f) => f.field)]; + const { allowedTypes } = this.props; + const filterFields = ['type', 'namespaces']; const { queryText, parsedParams } = parseQuery(this.state.activeQuery, filterFields); const { type: visibleTypes, namespaces } = parsedParams; @@ -236,8 +236,8 @@ export class SavedObjectsTable extends Component { const { activeQuery: query, page, perPage } = this.state; - const { notifications, http, allowedTypes, filterRegistry } = this.props; - const filterFields = ['type', ...filterRegistry.getAll().map((f) => f.field)]; + const { notifications, http, allowedTypes } = this.props; + const filterFields = ['type', 'namespaces']; const { queryText, parsedParams } = parseQuery(query, filterFields); const { type: visibleTypes, namespaces } = parsedParams; const filteredTypes = allowedTypes.filter( @@ -405,9 +405,9 @@ export class SavedObjectsTable extends Component { const { exportAllSelectedOptions, isIncludeReferencesDeepChecked, activeQuery } = this.state; - const { notifications, http, filterRegistry } = this.props; + const { notifications, http } = this.props; - const filterFields = ['type', ...filterRegistry.getAll().map((f) => f.field)]; + const filterFields = ['type', 'namespaces']; const { queryText } = parseQuery(activeQuery, filterFields); const exportTypes = Object.entries(exportAllSelectedOptions).reduce((accum, [id, selected]) => { if (selected) { @@ -782,7 +782,7 @@ export class SavedObjectsTable extends Component { - const fieldCounts = savedObjectCounts[filter.field] || {}; - if (filter.options) { - filter.options.map((filterOption) => { - filterOption.view = `${filterOption.name} (${fieldCounts[filterOption.value] || 0})`; - }); - } - return { - ...filter, - 'data-test-subj': `savedObjectsFilter-${filter.id}`, - }; - }), // Add this back in once we have tag support // { // type: 'field_value_selection', @@ -827,6 +815,28 @@ export class SavedObjectsTable extends Component 0) { + const nsCounts = savedObjectCounts.namespaces || {}; + const nsFilterOptions = availableNamespaces.map((ns) => { + return { + name: ns.name, + value: ns.id, + view: `${ns.name} (${nsCounts[ns.id] || 0})`, + }; + }); + + filters.push({ + type: 'field_value_selection', + field: 'namespaces', + name: i18n.translate('savedObjectsManagement.objectsTable.table.namespaceFilterName', { + defaultMessage: 'Namespaces', + }), + multiSelect: 'or', + options: nsFilterOptions, + }); + } + return ( {this.renderFlyout()} @@ -846,11 +856,11 @@ export class SavedObjectsTable extends Component void; }) => { const capabilities = coreStart.application.capabilities; @@ -80,7 +80,7 @@ const SavedObjectsTablePage = ({ serviceRegistry={serviceRegistry} actionRegistry={actionRegistry} columnRegistry={columnRegistry} - filterRegistry={filterRegistry} + namespaceRegistry={namespaceRegistry} savedObjectsClient={coreStart.savedObjects.client} indexPatterns={dataStart.indexPatterns} search={dataStart.search} diff --git a/src/plugins/saved_objects_management/public/plugin.ts b/src/plugins/saved_objects_management/public/plugin.ts index 537df8b51452..dedf1495c284 100644 --- a/src/plugins/saved_objects_management/public/plugin.ts +++ b/src/plugins/saved_objects_management/public/plugin.ts @@ -45,9 +45,9 @@ import { SavedObjectsManagementColumnService, SavedObjectsManagementColumnServiceSetup, SavedObjectsManagementColumnServiceStart, - SavedObjectsManagementFilterService, - SavedObjectsManagementFilterServiceSetup, - SavedObjectsManagementFilterServiceStart, + SavedObjectsManagementNamespaceService, + SavedObjectsManagementNamespaceServiceSetup, + SavedObjectsManagementNamespaceServiceStart, SavedObjectsManagementServiceRegistry, ISavedObjectsManagementServiceRegistry, } from './services'; @@ -56,14 +56,14 @@ import { registerServices } from './register_services'; export interface SavedObjectsManagementPluginSetup { actions: SavedObjectsManagementActionServiceSetup; columns: SavedObjectsManagementColumnServiceSetup; - filters: SavedObjectsManagementFilterServiceSetup; + namespaces: SavedObjectsManagementNamespaceServiceSetup; serviceRegistry: ISavedObjectsManagementServiceRegistry; } export interface SavedObjectsManagementPluginStart { actions: SavedObjectsManagementActionServiceStart; columns: SavedObjectsManagementColumnServiceStart; - filters: SavedObjectsManagementFilterServiceStart; + namespaces: SavedObjectsManagementNamespaceServiceStart; } export interface SetupDependencies { @@ -89,7 +89,7 @@ export class SavedObjectsManagementPlugin > { private actionService = new SavedObjectsManagementActionService(); private columnService = new SavedObjectsManagementColumnService(); - private filterService = new SavedObjectsManagementFilterService(); + private namespaceService = new SavedObjectsManagementNamespaceService(); private serviceRegistry = new SavedObjectsManagementServiceRegistry(); public setup( @@ -98,7 +98,7 @@ export class SavedObjectsManagementPlugin ): SavedObjectsManagementPluginSetup { const actionSetup = this.actionService.setup(); const columnSetup = this.columnService.setup(); - const filterSetup = this.filterService.setup(); + const namespaceSetup = this.namespaceService.setup(); if (home) { home.featureCatalogue.register({ @@ -140,7 +140,7 @@ export class SavedObjectsManagementPlugin return { actions: actionSetup, columns: columnSetup, - filters: filterSetup, + namespaces: namespaceSetup, serviceRegistry: this.serviceRegistry, }; } @@ -148,12 +148,12 @@ export class SavedObjectsManagementPlugin public start(core: CoreStart, { data }: StartDependencies) { const actionStart = this.actionService.start(); const columnStart = this.columnService.start(); - const filterStart = this.filterService.start(); + const namespaceStart = this.namespaceService.start(); return { actions: actionStart, columns: columnStart, - filters: filterStart, + namespaces: namespaceStart, }; } } diff --git a/src/plugins/saved_objects_management/public/services/filter_service.ts b/src/plugins/saved_objects_management/public/services/filter_service.ts deleted file mode 100644 index 2c903a1d335e..000000000000 --- a/src/plugins/saved_objects_management/public/services/filter_service.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -import { SavedObjectsManagementFilter } from './types'; - -export interface SavedObjectsManagementFilterServiceSetup { - /** - * register given filter in the registry. - */ - register: (filter: SavedObjectsManagementFilter) => void; -} - -export interface SavedObjectsManagementFilterServiceStart { - /** - * return all {@link SavedObjectsManagementFilter | filters} currently registered. - */ - getAll: () => Array>; -} - -export class SavedObjectsManagementFilterService { - private readonly filters = new Map>(); - - setup(): SavedObjectsManagementFilterServiceSetup { - return { - register: (filter) => { - if (this.filters.has(filter.id)) { - throw new Error(`Saved Objects Management Filter with id '${filter.id}' already exists`); - } - this.filters.set(filter.id, filter); - }, - }; - } - - start(): SavedObjectsManagementFilterServiceStart { - return { - getAll: () => [...this.filters.values()], - }; - } -} diff --git a/src/plugins/saved_objects_management/public/services/index.ts b/src/plugins/saved_objects_management/public/services/index.ts index 9a23058d148e..498ea683384d 100644 --- a/src/plugins/saved_objects_management/public/services/index.ts +++ b/src/plugins/saved_objects_management/public/services/index.ts @@ -39,10 +39,10 @@ export { SavedObjectsManagementColumnServiceSetup, } from './column_service'; export { - SavedObjectsManagementFilterService, - SavedObjectsManagementFilterServiceStart, - SavedObjectsManagementFilterServiceSetup, -} from './filter_service'; + SavedObjectsManagementNamespaceService, + SavedObjectsManagementNamespaceServiceStart, + SavedObjectsManagementNamespaceServiceSetup, +} from './namespace_service'; export { SavedObjectsManagementServiceRegistry, ISavedObjectsManagementServiceRegistry, @@ -51,6 +51,6 @@ export { export { SavedObjectsManagementAction, SavedObjectsManagementColumn, - SavedObjectsManagementFilter, + SavedObjectsManagementNamespace, SavedObjectsManagementRecord, } from './types'; diff --git a/src/plugins/saved_objects_management/public/services/filter_service.mock.ts b/src/plugins/saved_objects_management/public/services/namespace_service.mock.ts similarity index 61% rename from src/plugins/saved_objects_management/public/services/filter_service.mock.ts rename to src/plugins/saved_objects_management/public/services/namespace_service.mock.ts index 73dd33fee2d6..309d90482037 100644 --- a/src/plugins/saved_objects_management/public/services/filter_service.mock.ts +++ b/src/plugins/saved_objects_management/public/services/namespace_service.mock.ts @@ -10,19 +10,19 @@ */ import { - SavedObjectsManagementFilterService, - SavedObjectsManagementFilterServiceSetup, - SavedObjectsManagementFilterServiceStart, -} from './filter_service'; + SavedObjectsManagementNamespaceService, + SavedObjectsManagementNamespaceServiceSetup, + SavedObjectsManagementNamespaceServiceStart, +} from './namespace_service'; -const createSetupMock = (): jest.Mocked => { +const createSetupMock = (): jest.Mocked => { const mock = { register: jest.fn(), }; return mock; }; -const createStartMock = (): jest.Mocked => { +const createStartMock = (): jest.Mocked => { const mock = { has: jest.fn(), getAll: jest.fn(), @@ -34,7 +34,9 @@ const createStartMock = (): jest.Mocked> => { +const createServiceMock = (): jest.Mocked< + PublicMethodsOf +> => { const mock = { setup: jest.fn().mockReturnValue(createSetupMock()), start: jest.fn().mockReturnValue(createStartMock()), @@ -42,7 +44,7 @@ const createServiceMock = (): jest.Mocked) => void; +} + +export interface SavedObjectsManagementNamespaceServiceStart { + /** + * return all {@link SavedObjectsManagementNamespace | namespaces} currently registered. + */ + getAll: () => Array>; +} + +export class SavedObjectsManagementNamespaceService { + private readonly namespaces = new Map>(); + + setup(): SavedObjectsManagementNamespaceServiceSetup { + return { + register: (ns) => { + if (this.namespaces.has(ns.id)) { + throw new Error(`Saved Objects Management Namespace with id '${ns.id}' already exists`); + } + this.namespaces.set(ns.id, ns); + }, + }; + } + + start(): SavedObjectsManagementNamespaceServiceStart { + return { + getAll: () => [...this.namespaces.values()], + }; + } +} diff --git a/src/plugins/saved_objects_management/public/services/types/filter.ts b/src/plugins/saved_objects_management/public/services/types/namespace.ts similarity index 56% rename from src/plugins/saved_objects_management/public/services/types/filter.ts rename to src/plugins/saved_objects_management/public/services/types/namespace.ts index 7e737c00dbfa..3a47f273c150 100644 --- a/src/plugins/saved_objects_management/public/services/types/filter.ts +++ b/src/plugins/saved_objects_management/public/services/types/namespace.ts @@ -9,17 +9,7 @@ * GitHub history for details. */ -interface SavedObjectsManagementFilterOption { - value: string; - name: string; - view: string; -} - -export interface SavedObjectsManagementFilter { +export interface SavedObjectsManagementNamespace { id: string; - type: string; - field: string; name: string; - multiSelect: string; - options: SavedObjectsManagementFilterOption; } From d2098e804958898adf433ce3f410296539490a67 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 26 Oct 2022 16:59:22 -0400 Subject: [PATCH 19/23] Add ability to register an alias Signed-off-by: Craig Perkins --- .../objects_table/saved_objects_table.tsx | 3 ++- .../public/services/namespace_service.mock.ts | 2 ++ .../public/services/namespace_service.ts | 7 +++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index a880c02c17cc..6f76e6fc233c 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -826,11 +826,12 @@ export class SavedObjectsTable extends Component) => void; + registerAlias: (alias: string) => void; } export interface SavedObjectsManagementNamespaceServiceStart { @@ -23,10 +24,12 @@ export interface SavedObjectsManagementNamespaceServiceStart { * return all {@link SavedObjectsManagementNamespace | namespaces} currently registered. */ getAll: () => Array>; + getAlias: () => string; } export class SavedObjectsManagementNamespaceService { private readonly namespaces = new Map>(); + private readonly alias; setup(): SavedObjectsManagementNamespaceServiceSetup { return { @@ -36,12 +39,16 @@ export class SavedObjectsManagementNamespaceService { } this.namespaces.set(ns.id, ns); }, + registerAlias: (alias) => { + this.alias = alias; + }, }; } start(): SavedObjectsManagementNamespaceServiceStart { return { getAll: () => [...this.namespaces.values()], + getAlias: () => this.alias, }; } } From 3331bf2b9ea0556725b63ba6fcea6ec817d5f271 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 26 Oct 2022 18:29:02 -0400 Subject: [PATCH 20/23] Update parse query and add to CHANGELOG Signed-off-by: Craig Perkins --- CHANGELOG.md | 1 + .../public/lib/parse_query.test.ts | 8 ++----- .../public/lib/parse_query.ts | 21 ++++++++++--------- .../objects_table/saved_objects_table.tsx | 15 +++++-------- 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31bcee4a2e9e..84e4a25890db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * [Multi DataSource] Address UX comments on Data source list and create page ([#2625](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2625)) * [Vis Builder] Rename wizard to visBuilder in i18n id and formatted message id ([#2635](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2635)) * [Vis Builder] Rename wizard to visBuilder in class name, type name and function name ([#2639](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2639)) +* Add extension point in saved object management to register namespaces and show filter ([#2656](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2656)) ### 🐛 Bug Fixes * [Vis Builder] Fixes auto bounds for timeseries bar chart visualization ([2401](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2401)) diff --git a/src/plugins/saved_objects_management/public/lib/parse_query.test.ts b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts index b4f3d1f10307..a940cf3ebbca 100644 --- a/src/plugins/saved_objects_management/public/lib/parse_query.test.ts +++ b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts @@ -45,12 +45,8 @@ describe('getQueryText', () => { }; expect(parseQuery({ ast } as any, ['type'])).toEqual({ queryText: 'foo bar', - parsedParams: { type: 'lala' }, - }); - - expect(parseQuery({ ast } as any, ['namespaces'])).toEqual({ - queryText: 'foo bar', - parsedParams: { namespaces: 'default' }, + visibleTypes: 'lala', + visibleNamespaces: 'default', }); }); }); diff --git a/src/plugins/saved_objects_management/public/lib/parse_query.ts b/src/plugins/saved_objects_management/public/lib/parse_query.ts index dabeb7126f13..24c35d500aaa 100644 --- a/src/plugins/saved_objects_management/public/lib/parse_query.ts +++ b/src/plugins/saved_objects_management/public/lib/parse_query.ts @@ -32,12 +32,13 @@ import { Query } from '@elastic/eui'; interface ParsedQuery { queryText?: string; - parsedParams?: any; + visibleTypes?: string[]; } -export function parseQuery(query: Query, filterFields: string[]): ParsedQuery { +export function parseQuery(query: Query): ParsedQuery { let queryText: string | undefined; - const parsedParams: any = {}; + let visibleTypes: string[] | undefined; + let visibleNamespaces: string[] | undefined; if (query) { if (query.ast.getTermClauses().length) { @@ -46,17 +47,17 @@ export function parseQuery(query: Query, filterFields: string[]): ParsedQuery { .map((clause: any) => clause.value) .join(' '); } - if (!!filterFields) { - filterFields.forEach((field) => { - if (query.ast.getFieldClauses(field)) { - parsedParams[field] = query.ast.getFieldClauses(field)[0].value as string[]; - } - }); + if (query.ast.getFieldClauses('type')) { + visibleTypes = query.ast.getFieldClauses('type')[0].value as string[]; + } + if (query.ast.getFieldClauses('namespaces')) { + visibleNamespaces = query.ast.getFieldClauses('namespaces')[0].value as string[]; } } return { queryText, - parsedParams, + visibleTypes, + visibleNamespaces, }; } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 6f76e6fc233c..f0f069f59f8c 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -179,9 +179,7 @@ export class SavedObjectsTable extends Component { const { allowedTypes } = this.props; - const filterFields = ['type', 'namespaces']; - const { queryText, parsedParams } = parseQuery(this.state.activeQuery, filterFields); - const { type: visibleTypes, namespaces } = parsedParams; + const { queryText, visibleTypes, visibleNamespaces } = parseQuery(this.state.activeQuery); const filteredTypes = allowedTypes.filter( (type) => !visibleTypes || visibleTypes.includes(type) @@ -191,7 +189,7 @@ export class SavedObjectsTable extends Component { const { activeQuery: query, page, perPage } = this.state; const { notifications, http, allowedTypes } = this.props; - const filterFields = ['type', 'namespaces']; - const { queryText, parsedParams } = parseQuery(query, filterFields); - const { type: visibleTypes, namespaces } = parsedParams; + const { queryText, visibleTypes, visibleNamespaces } = parseQuery(query); const filteredTypes = allowedTypes.filter( (type) => !visibleTypes || visibleTypes.includes(type) ); @@ -251,7 +247,7 @@ export class SavedObjectsTable extends Component 1) { findOptions.sortField = 'type'; @@ -407,8 +403,7 @@ export class SavedObjectsTable extends Component { if (selected) { accum.push(id); From ad80403937d0d3be21886bc7fc5522fa55e91ee7 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 27 Oct 2022 12:06:01 -0400 Subject: [PATCH 21/23] Remove commented out code Signed-off-by: Craig Perkins --- .../objects_table/saved_objects_table.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index f0f069f59f8c..df7535ae572f 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -800,14 +800,6 @@ export class SavedObjectsTable extends Component Date: Thu, 27 Oct 2022 16:25:28 -0400 Subject: [PATCH 22/23] Address code review comments Signed-off-by: Craig Perkins --- .../public/services/namespace_service.mock.ts | 3 +-- .../public/services/namespace_service.ts | 5 +++++ .../server/routes/scroll_count.ts | 8 +++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/plugins/saved_objects_management/public/services/namespace_service.mock.ts b/src/plugins/saved_objects_management/public/services/namespace_service.mock.ts index 35953d37a66d..d1599920e3ce 100644 --- a/src/plugins/saved_objects_management/public/services/namespace_service.mock.ts +++ b/src/plugins/saved_objects_management/public/services/namespace_service.mock.ts @@ -18,18 +18,17 @@ import { const createSetupMock = (): jest.Mocked => { const mock = { register: jest.fn(), + registerAlias: jest.fn(), }; return mock; }; const createStartMock = (): jest.Mocked => { const mock = { - has: jest.fn(), getAll: jest.fn(), getAlias: jest.fn(), }; - mock.has.mockReturnValue(true); mock.getAll.mockReturnValue([]); mock.getAlias.mockReturnValue('Namespace'); diff --git a/src/plugins/saved_objects_management/public/services/namespace_service.ts b/src/plugins/saved_objects_management/public/services/namespace_service.ts index ebb151004a99..5b1a797ae2da 100644 --- a/src/plugins/saved_objects_management/public/services/namespace_service.ts +++ b/src/plugins/saved_objects_management/public/services/namespace_service.ts @@ -40,6 +40,11 @@ export class SavedObjectsManagementNamespaceService { this.namespaces.set(ns.id, ns); }, registerAlias: (alias) => { + if (!!this.alias) { + throw new Error( + `An alias has already been registered. Cannot register more than one alias.` + ); + } this.alias = alias; }, }; diff --git a/src/plugins/saved_objects_management/server/routes/scroll_count.ts b/src/plugins/saved_objects_management/server/routes/scroll_count.ts index 20d1aa6aea9f..4069eac17de1 100644 --- a/src/plugins/saved_objects_management/server/routes/scroll_count.ts +++ b/src/plugins/saved_objects_management/server/routes/scroll_count.ts @@ -58,7 +58,6 @@ export const registerScrollForCountRoute = (router: IRouter) => { } const findOptions: SavedObjectsFindOptions = { - ...req.body.params, type: req.body.typesToInclude, perPage: 1000, }; @@ -101,6 +100,13 @@ export const registerScrollForCountRoute = (router: IRouter) => { } } + const namespacesToInclude = req.body.namespacesToInclude || []; + for (const ns of namespacesToInclude) { + if (!counts.namespaces[ns]) { + counts.namespaces[ns] = 0; + } + } + return res.ok({ body: counts, }); From 26305668f89c1758346ba0a970fc1ae3c6a665bd Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 27 Oct 2022 18:09:49 -0400 Subject: [PATCH 23/23] Override i18n if alias is regitered Signed-off-by: Craig Perkins --- .../objects_table/saved_objects_table.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index df7535ae572f..da0f3d8abc40 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -813,13 +813,14 @@ export class SavedObjectsTable extends Component