Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Maps] saved object tagging #83197

Merged
merged 18 commits into from
Nov 17, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ export interface TableListViewProps {
listingLimit: number;
initialFilter: string;
initialPageSize: number;
noItemsFragment: JSX.Element;
noItemsFragment?: JSX.Element;
tableColumns: Array<EuiBasicTableColumn<any>>;
tableListTitle: string;
toastNotifications: ToastsStart;
@@ -73,7 +73,7 @@ export interface TableListViewProps {
/**
* Describes the content of the table. If not specified, the caption will be "This table contains {itemCount} rows."
*/
tableCaption: string;
tableCaption?: string;
searchFilters?: SearchFilterConfig[];
}

@@ -445,6 +445,7 @@ class TableListView extends React.Component<TableListViewProps, TableListViewSta
defaultQuery: this.state.filter,
box: {
incremental: true,
'data-test-subj': 'tableListSearchBox',
},
filters: searchFilters ?? [],
};
4 changes: 1 addition & 3 deletions test/functional/page_objects/dashboard_page.ts
Original file line number Diff line number Diff line change
@@ -126,9 +126,7 @@ export function DashboardPageProvider({ getService, getPageObjects }: FtrProvide
*/
public async onDashboardLandingPage() {
log.debug(`onDashboardLandingPage`);
return await testSubjects.exists('dashboardLandingPage', {
timeout: 5000,
});
return await listingTable.onListingPage('dashboard');
}

public async expectExistsDashboardLandingPage() {
31 changes: 13 additions & 18 deletions test/functional/services/listing_table.ts
Original file line number Diff line number Diff line change
@@ -20,21 +20,19 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';

type AppName = 'visualize' | 'dashboard' | 'map';

export function ListingTableProvider({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const find = getService('find');
const log = getService('log');
const retry = getService('retry');
const { common, header } = getPageObjects(['common', 'header']);
const prefixMap = { visualize: 'vis', dashboard: 'dashboard' };
const prefixMap = { visualize: 'vis', dashboard: 'dashboard', map: 'map' };

/**
* This class provides functions for dashboard and visualize landing pages
*/
class ListingTable {
private async getSearchFilter() {
const searchFilter = await find.allByCssSelector('main .euiFieldSearch');
return searchFilter[0];
return await testSubjects.find('tableListSearchBox');
}

/**
@@ -86,9 +84,8 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider

/**
* Returns items count on landing page
* @param appName 'visualize' | 'dashboard'
*/
public async expectItemsCount(appName: 'visualize' | 'dashboard', count: number) {
public async expectItemsCount(appName: AppName, count: number) {
await retry.try(async () => {
const elements = await find.allByCssSelector(
`[data-test-subj^="${prefixMap[appName]}ListingTitleLink"]`
@@ -126,14 +123,8 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider

/**
* Searches for item on Landing page and retruns items count that match `ListingTitleLink-${name}` pattern
* @param appName 'visualize' | 'dashboard'
* @param name item name
*/
public async searchAndExpectItemsCount(
appName: 'visualize' | 'dashboard',
name: string,
count: number
) {
public async searchAndExpectItemsCount(appName: AppName, name: string, count: number) {
await this.searchForItemWithName(name);
await retry.try(async () => {
const links = await testSubjects.findAll(
@@ -165,10 +156,8 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider

/**
* Clicks item on Landing page by link name if it is present
* @param appName 'dashboard' | 'visualize'
* @param name item name
*/
public async clickItemLink(appName: 'dashboard' | 'visualize', name: string) {
public async clickItemLink(appName: AppName, name: string) {
await testSubjects.click(
`${prefixMap[appName]}ListingTitleLink-${name.split(' ').join('-')}`
);
@@ -204,6 +193,12 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider
}
});
}

public async onListingPage(appName: AppName) {
return await testSubjects.exists(`${appName}LandingPage`, {
timeout: 5000,
});
}
}

return new ListingTable();
2 changes: 1 addition & 1 deletion x-pack/plugins/maps/kibana.json
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@
"savedObjects",
"share"
],
"optionalPlugins": ["home"],
"optionalPlugins": ["home", "savedObjectsTagging"],
"ui": true,
"server": true,
"extraPublicDirs": ["common/constants"],
1 change: 1 addition & 0 deletions x-pack/plugins/maps/public/kibana_services.ts
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@ export const getCoreI18n = () => coreStart.i18n;
export const getSearchService = () => pluginsStart.data.search;
export const getEmbeddableService = () => pluginsStart.embeddable;
export const getNavigateToApp = () => coreStart.application.navigateToApp;
export const getSavedObjectsTagging = () => pluginsStart.savedObjectsTagging;

// xpack.maps.* kibana.yml settings from this plugin
let mapAppConfig: MapsConfigType;
32 changes: 19 additions & 13 deletions x-pack/plugins/maps/public/map_attribute_service.ts
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { SavedObjectReference } from 'src/core/types';
import { AttributeService } from '../../../../src/plugins/embeddable/public';
import { MapSavedObjectAttributes } from '../common/map_saved_object_type';
import { MAP_SAVED_OBJECT_TYPE } from '../common/constants';
@@ -14,11 +15,9 @@ import { getCoreOverlays, getEmbeddableService, getSavedObjectsClient } from './
import { extractReferences, injectReferences } from '../common/migrations/references';
import { MapByValueInput, MapByReferenceInput } from './embeddable/types';

export type MapAttributeService = AttributeService<
MapSavedObjectAttributes,
MapByValueInput,
MapByReferenceInput
>;
type MapDoc = MapSavedObjectAttributes & { references?: SavedObjectReference[] };

export type MapAttributeService = AttributeService<MapDoc, MapByValueInput, MapByReferenceInput>;

let mapAttributeService: MapAttributeService | null = null;

@@ -28,30 +27,37 @@ export function getMapAttributeService(): MapAttributeService {
}

mapAttributeService = getEmbeddableService().getAttributeService<
MapSavedObjectAttributes,
MapDoc,
MapByValueInput,
MapByReferenceInput
>(MAP_SAVED_OBJECT_TYPE, {
saveMethod: async (attributes: MapSavedObjectAttributes, savedObjectId?: string) => {
const { attributes: attributesWithExtractedReferences, references } = extractReferences({
attributes,
saveMethod: async (attributes: MapDoc, savedObjectId?: string) => {
// AttributeService "attributes" contains "references" as a child.
// SavedObjectClient "attributes" uses "references" as a sibling.
// https://github.com/elastic/kibana/issues/83133
const savedObjectClientReferences = attributes.references;
const savedObjectClientAttributes = { ...attributes };
delete savedObjectClientAttributes.references;
const { attributes: updatedAttributes, references } = extractReferences({
attributes: savedObjectClientAttributes,
references: savedObjectClientReferences,
});

const savedObject = await (savedObjectId
? getSavedObjectsClient().update<MapSavedObjectAttributes>(
MAP_SAVED_OBJECT_TYPE,
savedObjectId,
attributesWithExtractedReferences,
updatedAttributes,
{ references }
)
: getSavedObjectsClient().create<MapSavedObjectAttributes>(
MAP_SAVED_OBJECT_TYPE,
attributesWithExtractedReferences,
updatedAttributes,
{ references }
));
return { id: savedObject.id };
},
unwrapMethod: async (savedObjectId: string): Promise<MapSavedObjectAttributes> => {
unwrapMethod: async (savedObjectId: string): Promise<MapDoc> => {
const savedObject = await getSavedObjectsClient().get<MapSavedObjectAttributes>(
MAP_SAVED_OBJECT_TYPE,
savedObjectId
@@ -62,7 +68,7 @@ export function getMapAttributeService(): MapAttributeService {
}

const { attributes } = injectReferences(savedObject);
return attributes;
return { ...attributes, references: savedObject.references };
},
checkForDuplicateTitle: (props: OnSaveProps) => {
return checkForDuplicateTitle(
2 changes: 2 additions & 0 deletions x-pack/plugins/maps/public/plugin.ts
Original file line number Diff line number Diff line change
@@ -63,6 +63,7 @@ import {
setLicensingPluginStart,
} from './licensed_features';
import { EMSSettings } from '../common/ems_settings';
import { SavedObjectTaggingPluginStart } from '../../saved_objects_tagging/public';

export interface MapsPluginSetupDependencies {
inspector: InspectorSetupContract;
@@ -86,6 +87,7 @@ export interface MapsPluginStartDependencies {
visualizations: VisualizationsStart;
savedObjects: SavedObjectsStart;
dashboard: DashboardStart;
savedObjectsTagging?: SavedObjectTaggingPluginStart;
}

/**
Loading