Skip to content

Commit 4de7358

Browse files
Merge branch 'main' into fixing-dfa-wizard-for-data-views-with-runtime-fields
2 parents 4235374 + c3ceef2 commit 4de7358

63 files changed

Lines changed: 1381 additions & 598 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/platform/packages/shared/deeplinks/security/deep_links.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@
1010
export enum SecurityPageName {
1111
administration = 'administration',
1212
alerts = 'alerts',
13+
attacks = 'attacks',
1314
aiValue = 'ai_value',
1415
assetInventory = 'asset_inventory',
1516
attackDiscovery = 'attack_discovery',
1617
blocklist = 'blocklist',
18+
19+
// TODO: https://github.com/elastic/kibana/issues/242434
20+
// Investigate possibility of using `detections` instead
21+
alertDetections = 'alert_detections',
22+
1723
/*
1824
* Warning: Computed values are not permitted in an enum with string valued members
1925
* All Cases page names must match `CasesDeepLinkId` in x-pack/platform/plugins/shared/cases/public/common/navigation/deep_links.ts

src/platform/plugins/shared/dashboard/common/content_management/constants.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const DEFAULT_PANEL_HEIGHT = 15;
1919
export const DEFAULT_DASHBOARD_OPTIONS = {
2020
hidePanelTitles: false,
2121
useMargins: true,
22-
syncColors: true,
22+
syncColors: false,
2323
syncCursor: true,
24-
syncTooltips: true,
24+
syncTooltips: false,
2525
} as const;

src/platform/plugins/shared/dashboard/public/dashboard_api/save_modal/save_dashboard.test.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,6 @@ jest.mock('../../dashboard_client', () => ({
2424
},
2525
}));
2626

27-
/* contentManagementService.client.create = jest.fn().mockImplementation(({ options }) => {
28-
if (options.id === undefined) {
29-
return { item: { id: 'newlyGeneratedId' } };
30-
}
31-
32-
throw new Error('Update should be used when id is provided');
33-
});
34-
35-
contentManagementService.client.update = jest.fn().mockImplementation(({ id }) => {
36-
if (id === undefined) {
37-
throw new Error('Update needs an id');
38-
}
39-
return { item: { id } };
40-
});*/
41-
4227
describe('Save dashboard state', () => {
4328
beforeEach(() => {
4429
jest.resetAllMocks();
@@ -68,7 +53,7 @@ describe('Save dashboard state', () => {
6853
});
6954

7055
it('should save the dashboard using a new id, and return redirect required', async () => {
71-
mockCreate.mockResolvedValue({ item: { id: 'newlyGeneratedId' } });
56+
mockCreate.mockResolvedValue({ id: 'newlyGeneratedId' });
7257
const result = await saveDashboard({
7358
dashboardState: {
7459
...getSampleDashboardState(),

src/platform/plugins/shared/dashboard/public/dashboard_api/save_modal/save_dashboard.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,9 @@ export const saveDashboard = async ({
2525
const idToSaveTo = saveOptions.saveAsCopy ? undefined : lastSavedId;
2626

2727
try {
28-
const result = idToSaveTo
29-
? await dashboardClient.update(idToSaveTo, dashboardState, references)
30-
: await dashboardClient.create(dashboardState, references);
31-
32-
const newId = result.item.id;
28+
const newId = idToSaveTo
29+
? (await dashboardClient.update(idToSaveTo, dashboardState, references)).item.id
30+
: (await dashboardClient.create(dashboardState, references)).id;
3331

3432
if (newId) {
3533
coreServices.notifications.toasts.addSuccess({

src/platform/plugins/shared/dashboard/public/dashboard_api/settings_manager.test.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,44 @@ import { BehaviorSubject } from 'rxjs';
1111
import { getSampleDashboardState } from '../mocks';
1212
import type { DashboardState } from '../../common';
1313
import { initializeSettingsManager } from './settings_manager';
14+
import { DEFAULT_DASHBOARD_OPTIONS } from '../../common/content_management';
1415

1516
describe('initializeSettingsManager', () => {
17+
describe('default values', () => {
18+
test('Should set syncCursor to false when value not provided', () => {
19+
const settingsManager = initializeSettingsManager({
20+
title: 'dashboard 1',
21+
panels: [],
22+
});
23+
expect(settingsManager.api.getSettings().syncColors).toBe(false);
24+
});
25+
26+
test('Should set syncTooltips to false when value not provided', () => {
27+
const settingsManager = initializeSettingsManager({
28+
title: 'dashboard 1',
29+
panels: [],
30+
});
31+
expect(settingsManager.api.getSettings().syncTooltips).toBe(false);
32+
});
33+
});
34+
35+
describe('setSettings', () => {
36+
test('Should not overwrite settings when setting partial state', () => {
37+
const settingsManager = initializeSettingsManager({
38+
title: 'dashboard 1',
39+
panels: [],
40+
options: {
41+
...DEFAULT_DASHBOARD_OPTIONS,
42+
useMargins: false,
43+
},
44+
});
45+
settingsManager.api.setSettings({ timeRestore: true });
46+
const settings = settingsManager.api.getSettings();
47+
expect(settings.timeRestore).toBe(true);
48+
expect(settings.useMargins).toBe(false);
49+
});
50+
});
51+
1652
describe('startComparing$', () => {
1753
test('Should return no changes when there are no changes', (done) => {
1854
const lastSavedState$ = new BehaviorSubject<DashboardState>(getSampleDashboardState());

src/platform/plugins/shared/dashboard/public/dashboard_api/settings_manager.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,12 @@ export function initializeSettingsManager(initialState: DashboardState) {
7979
syncTooltips$: stateManager.api.syncTooltips$,
8080
useMargins$: stateManager.api.useMargins$,
8181
},
82-
setSettings: stateManager.reinitializeState,
82+
setSettings: (settings: Partial<DashboardSettings>) => {
83+
stateManager.reinitializeState({
84+
...stateManager.getLatestState(),
85+
...settings,
86+
});
87+
},
8388
setTags: stateManager.api.setTags,
8489
timeRestore$: stateManager.api.timeRestore$,
8590
title$: stateManager.api.title$,

src/platform/plugins/shared/dashboard/public/dashboard_client/dashboard_client.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ import type { Reference } from '@kbn/content-management-utils';
1414
import { CONTENT_ID, DASHBOARD_API_VERSION } from '../../common/content_management/constants';
1515
import type {
1616
DashboardAPIGetOut,
17-
DashboardCreateIn,
18-
DashboardCreateOut,
1917
DashboardSearchAPIResult,
2018
DashboardSearchIn,
2119
DashboardState,
@@ -36,13 +34,14 @@ const cache = new LRUCache<string, DashboardAPIGetOut>({
3634

3735
export const dashboardClient = {
3836
create: async (dashboardState: DashboardState, references: Reference[]) => {
39-
// TODO replace with call to dashboard REST create endpoint
40-
return contentManagementService.client.create<DashboardCreateIn, DashboardCreateOut>({
41-
contentTypeId: DASHBOARD_CONTENT_ID,
42-
data: dashboardState,
43-
options: {
44-
references,
45-
},
37+
return coreServices.http.post<DashboardAPIGetOut>(`/api/dashboards/dashboard`, {
38+
version: DASHBOARD_API_VERSION,
39+
body: JSON.stringify({
40+
data: {
41+
...dashboardState,
42+
references,
43+
},
44+
}),
4645
});
4746
},
4847
delete: async (id: string): Promise<DeleteResult> => {

src/platform/plugins/shared/dashboard/server/api/constants.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,29 @@ export const PUBLIC_API_PATH = '/api/dashboards/dashboard';
1414
* const will be removed and a PUBLIC_API_VERSION (ex. 2023-10-31) will be introduced.
1515
*/
1616
export const INTERNAL_API_VERSION = '1';
17+
18+
export const commonRouteConfig = {
19+
// This route is in development and not yet intended for public use.
20+
access: 'internal',
21+
/**
22+
* `enableQueryVersion` is a temporary solution for testing internal endpoints.
23+
* Requests to these internal endpoints from Kibana Dev Tools or external clients
24+
* should include the ?apiVersion=1 query parameter.
25+
* This will be removed when the API is finalized and moved to a stable version.
26+
*/
27+
enableQueryVersion: true,
28+
description:
29+
'This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.',
30+
options: {
31+
tags: ['oas-tag:Dashboards'],
32+
availability: {
33+
stability: 'experimental',
34+
},
35+
},
36+
security: {
37+
authz: {
38+
enabled: false,
39+
reason: 'Relies on Content Client for authorization',
40+
},
41+
},
42+
} as const;
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
import Boom from '@hapi/boom';
11+
import type { RequestHandlerContext } from '@kbn/core/server';
12+
import type { Reference } from '@kbn/content-management-utils';
13+
import type { DashboardSavedObjectAttributes } from '../../dashboard_saved_object';
14+
import { DASHBOARD_SAVED_OBJECT_TYPE } from '../../dashboard_saved_object';
15+
import type { DashboardCreateRequestBody, DashboardCreateResponseBody } from './types';
16+
import {
17+
transformDashboardIn,
18+
transformDashboardOut,
19+
transformReferencesOut,
20+
} from '../../content_management/v1/transforms';
21+
import type { DashboardState } from '../../content_management';
22+
23+
export async function create(
24+
requestCtx: RequestHandlerContext,
25+
searchBody: DashboardCreateRequestBody
26+
): Promise<DashboardCreateResponseBody> {
27+
const { core } = await requestCtx.resolve(['core']);
28+
29+
const { references: incomingReferences, ...incomingDashboardState } = searchBody.data;
30+
const {
31+
attributes: soAttributes,
32+
references: soReferences,
33+
error: transformInError,
34+
} = transformDashboardIn({
35+
dashboardState: incomingDashboardState,
36+
incomingReferences,
37+
});
38+
if (transformInError) {
39+
throw Boom.badRequest(`Invalid data. ${transformInError.message}`);
40+
}
41+
42+
const savedObject = await core.savedObjects.client.create<DashboardSavedObjectAttributes>(
43+
DASHBOARD_SAVED_OBJECT_TYPE,
44+
soAttributes,
45+
{
46+
references: soReferences,
47+
...(searchBody.id && { id: searchBody.id }),
48+
...(searchBody.spaces && { initialNamespaces: searchBody.spaces }),
49+
}
50+
);
51+
52+
let dashboardState: DashboardState;
53+
let references: Reference[];
54+
try {
55+
dashboardState = transformDashboardOut(
56+
savedObject.attributes,
57+
savedObject.references
58+
) as DashboardState;
59+
references = transformReferencesOut(savedObject.references, dashboardState.panels);
60+
} catch (transformOutError) {
61+
throw Boom.badRequest(`Invalid response. ${transformOutError.message}`);
62+
}
63+
64+
return {
65+
id: savedObject.id,
66+
data: {
67+
...dashboardState,
68+
references,
69+
},
70+
meta: {
71+
createdAt: savedObject.created_at,
72+
createdBy: savedObject.created_by,
73+
error: savedObject.error,
74+
managed: savedObject.managed,
75+
updatedAt: savedObject.updated_at,
76+
updatedBy: savedObject.updated_by,
77+
version: savedObject.version ?? '',
78+
},
79+
spaces: savedObject.namespaces,
80+
};
81+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
export type { DashboardCreateRequestBody, DashboardCreateResponseBody } from './types';
11+
export { registerCreateRoute } from './register_create_route';

0 commit comments

Comments
 (0)