Skip to content
Merged
Show file tree
Hide file tree
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
Expand Up @@ -22,4 +22,5 @@ export interface CreateRuleBody<Params extends RuleTypeParams = RuleTypeParams>
notifyWhen?: Rule<Params>['notifyWhen'];
alertDelay?: Rule<Params>['alertDelay'];
flapping?: Rule<Params>['flapping'];
artifacts?: Rule<Params>['artifacts'];
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export interface UpdateRuleBody<Params extends RuleTypeParams = RuleTypeParams>
notifyWhen?: Rule<Params>['notifyWhen'];
alertDelay?: Rule<Params>['alertDelay'];
flapping?: Rule<Params>['flapping'];
artifacts?: Rule<Params>['artifacts'];
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const UPDATE_FIELDS: Array<keyof UpdateRuleBody> = [
'params',
'alertDelay',
'flapping',
'artifacts',
];

export const UPDATE_FIELDS_WITH_ACTIONS: Array<keyof UpdateRuleBody> = [
Expand All @@ -33,6 +34,7 @@ export const UPDATE_FIELDS_WITH_ACTIONS: Array<keyof UpdateRuleBody> = [
'alertDelay',
'actions',
'flapping',
'artifacts',
];

export async function updateRule({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*/

export * from './types';
export * from './services/dashboard_service';
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { dashboardServiceProvider } from './dashboard_service';
import { contentManagementMock } from '@kbn/content-management-plugin/public/mocks';

describe('DashboardService', () => {
const contentManagement = contentManagementMock.createStartContract();
const dashboardService = dashboardServiceProvider(contentManagement);

test('should fetch dashboards', async () => {
// arrange
const searchMock = jest.spyOn(contentManagement.client, 'search').mockResolvedValue({
total: 0,
hits: [],
});

// act
const resp = await dashboardService.fetchDashboards({ text: 'test*' });

// assert
expect(searchMock).toHaveBeenCalledWith({
contentTypeId: 'dashboard',
query: {
text: 'test*',
},
options: {
fields: ['title', 'description'],
spaces: ['*'],
},
});
expect(resp).toEqual([]);

searchMock.mockRestore();
});

test('should fetch dashboard by id', async () => {
// mock get to resolve with a dashboard
const getMock = jest.spyOn(contentManagement.client, 'get').mockResolvedValue({
item: {
error: null,
attributes: {
title: 'Dashboard 1',
},
references: [],
},
});

// act
const resp = await dashboardService.fetchDashboard('1');

// assert
expect(getMock).toHaveBeenCalledWith({ contentTypeId: 'dashboard', id: '1' });
expect(resp).toEqual({
status: 'success',
id: '1',
attributes: {
title: 'Dashboard 1',
},
references: [],
});

getMock.mockRestore();
});

test('should return an error if dashboard id is not found', async () => {
const getMock = jest.spyOn(contentManagement.client, 'get').mockRejectedValue({
message: 'Dashboard not found',
});

const resp = await dashboardService.fetchDashboard('2');
expect(getMock).toHaveBeenCalledWith({ contentTypeId: 'dashboard', id: '2' });
expect(resp).toEqual({
status: 'error',
id: '2',
error: 'Dashboard not found',
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import type { SearchQuery } from '@kbn/content-management-plugin/common';
import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import type { Reference, ContentManagementCrudTypes } from '@kbn/content-management-utils';
import type { SavedObjectError } from '@kbn/core/public';
import type { GetIn } from '@kbn/content-management-plugin/common';

const DASHBOARD_CONTENT_TYPE_ID = 'dashboard';
export type DashboardGetIn = GetIn<typeof DASHBOARD_CONTENT_TYPE_ID>;

export type FindDashboardsByIdResponse = { id: string } & (
| { status: 'success'; attributes: any; references: Reference[] }
| { status: 'error'; error: SavedObjectError }
);

export interface DashboardItem {
id: string;
attributes: any; // DashboardAttributes is exported in the Dashboard plugin and this causes a cycle dependency. Get feedback on the best approach here
}

export type DashboardService = ReturnType<typeof dashboardServiceProvider>;
export type DashboardItems = Awaited<ReturnType<DashboardService['fetchDashboards']>>;

export function dashboardServiceProvider(contentManagementService: ContentManagementPublicStart) {
return {
/**
* Fetch dashboards
* @param query - The query to search for dashboards
* @returns - The dashboards that match the query
*/
async fetchDashboards(query: SearchQuery = {}) {
const response = await contentManagementService.client.search({
contentTypeId: 'dashboard',
query,
options: { spaces: ['*'], fields: ['title', 'description'] },
});

// Assert the type of response to access hits property
return (response as { hits: DashboardItem[] }).hits;
},
/**
* Fetch dashboard by id
* @param id - The id of the dashboard to fetch
* @returns - The dashboard with the given id
* @throws - An error if the dashboard does not exist
*/
async fetchDashboard(id: string): Promise<FindDashboardsByIdResponse> {
try {
const response = await contentManagementService.client.get<
DashboardGetIn,
ContentManagementCrudTypes<
typeof DASHBOARD_CONTENT_TYPE_ID,
any,
object,
object,
object
>['GetOut']
>({
contentTypeId: 'dashboard',
id,
});
if (response.item.error) {
throw response.item.error;
}

return {
id,
status: 'success',
attributes: response.item.attributes,
references: response.item.references,
};
} catch (error) {
return {
status: 'error',
error: error.body || error.message,
id,
};
}
},

async fetchDashboardsByIds(ids: string[]) {
const findPromises = ids.map((id) => this.fetchDashboard(id));
const results = await Promise.all(findPromises);
return results as FindDashboardsByIdResponse[];
},
/**
* Fetch only the dashboards that still exist
* @param ids - The ids of the dashboards to fetch
* @returns - The dashboards that exist
*/
async fetchValidDashboards(ids: string[]) {
const responses = await this.fetchDashboardsByIds(ids);
const existingDashboards = responses.filter(({ status }) => status === 'success');
return existingDashboards;
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export const CreateRuleForm = (props: CreateRuleFormProps) => {
actions: newFormData.actions,
alertDelay: newFormData.alertDelay,
flapping: newFormData.flapping,
artifacts: newFormData.artifacts,
},
});
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export const EditRuleForm = (props: EditRuleFormProps) => {
actions: newFormData.actions,
alertDelay: newFormData.alertDelay,
flapping: newFormData.flapping,
artifacts: newFormData.artifacts,
},
});
},
Expand Down
Loading