mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 10:40:07 -04:00
[Dashboard] Add saved object version for collapsible sections (#222450)
Closes https://github.com/elastic/kibana/issues/222437 ## Summary Rather than [dynamically adding `sections` to V2 of the dashboard saved object](https://github.com/elastic/kibana/pull/220877/files#diff-98ad8ac0d2638b4dbc8ca6476730a22566c9e3d35fc92d32030a2d7eaf4159a7R82-R85), this PR adds a V3 saved object instead in order to add this new key (and removes it from V2) - this allows V2 saved objects to be properly updated to the new version. **Steps to reproduce:** 1. Start an ES server + Kibana on a version **before** collapsible sections merged 2. Download sample data on that same server 3. Launch a second Kibana from `main` on top of the same ES server started in step 1 4. Try to add a collapsible section on this new Kibana 5. You will hit an error when trying to save the dashboard 🔥 **Steps to test this fix:** 1. Follow steps 1 and 2 from the reproduction steps above 2. Launch a second Kibana from **this PR** on top of the same ES server started in step 1 3. Try to add a collapsible section on this new Kibana 4. You should be able to save your dashboard this time! 🎉 ### Before https://github.com/user-attachments/assets/e2af0f8b-cabb-4a56-86b3-36a6120cd91f ### After https://github.com/user-attachments/assets/480d7054-27aa-4661-8279-43bd761eaf44 ### Checklist - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
2564d6de38
commit
2ec8ca00b4
12 changed files with 114 additions and 40 deletions
|
@ -923,6 +923,7 @@
|
|||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"dynamic": false,
|
||||
"properties": {
|
||||
"controlGroupInput": {
|
||||
"properties": {
|
||||
|
|
|
@ -91,7 +91,7 @@ describe('checking migration metadata changes on all registered SO types', () =>
|
|||
"connector_token": "79977ea2cb1530ba7e315b95c1b5a524b622a6b3",
|
||||
"core-usage-stats": "b3c04da317c957741ebcdedfea4524049fdc79ff",
|
||||
"csp-rule-template": "c151324d5f85178169395eecb12bac6b96064654",
|
||||
"dashboard": "7fea2b6f8f860ac4f665fd0d5c91645ac248fd56",
|
||||
"dashboard": "904b7a17c97a8df4292fa411195c33c693aab510",
|
||||
"dynamic-config-overrides": "eb3ec7d96a42991068eda5421eecba9349c82d2b",
|
||||
"endpoint:unified-user-artifact-manifest": "71c7fcb52c658b21ea2800a6b6a76972ae1c776e",
|
||||
"endpoint:user-artifact-manifest": "1c3533161811a58772e30cdc77bac4631da3ef2b",
|
||||
|
|
|
@ -12,6 +12,8 @@ import { SavedObjectsType } from '@kbn/core/server';
|
|||
|
||||
import { dashboardAttributesSchema as dashboardAttributesSchemaV1 } from './schema/v1';
|
||||
import { dashboardAttributesSchema as dashboardAttributesSchemaV2 } from './schema/v2';
|
||||
import { dashboardAttributesSchema as dashboardAttributesSchemaV3 } from './schema/v3';
|
||||
|
||||
import {
|
||||
createDashboardSavedObjectTypeMigrations,
|
||||
DashboardSavedObjectTypeMigrationsDeps,
|
||||
|
@ -69,8 +71,23 @@ export const createDashboardSavedObjectType = ({
|
|||
create: dashboardAttributesSchemaV2,
|
||||
},
|
||||
},
|
||||
3: {
|
||||
changes: [
|
||||
{
|
||||
type: 'mappings_addition',
|
||||
addedMappings: {
|
||||
sections: { properties: {}, dynamic: false },
|
||||
},
|
||||
},
|
||||
],
|
||||
schemas: {
|
||||
forwardCompatibility: dashboardAttributesSchemaV3.extends({}, { unknowns: 'ignore' }),
|
||||
create: dashboardAttributesSchemaV3,
|
||||
},
|
||||
},
|
||||
},
|
||||
mappings: {
|
||||
dynamic: false,
|
||||
properties: {
|
||||
description: { type: 'text' },
|
||||
hits: { type: 'integer', index: false, doc_values: false },
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
// Latest model version for dashboard saved objects is v2
|
||||
// Latest model version for dashboard saved objects is v3
|
||||
export {
|
||||
dashboardAttributesSchema as dashboardSavedObjectSchema,
|
||||
type DashboardAttributes as DashboardSavedObjectAttributes,
|
||||
type GridData,
|
||||
type SavedDashboardPanel,
|
||||
type SavedDashboardSection,
|
||||
} from './v2';
|
||||
} from './v3';
|
||||
|
|
|
@ -7,10 +7,5 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
export type {
|
||||
DashboardAttributes,
|
||||
GridData,
|
||||
SavedDashboardPanel,
|
||||
SavedDashboardSection,
|
||||
} from './types';
|
||||
export type { DashboardAttributes, GridData, SavedDashboardPanel } from './types';
|
||||
export { controlGroupInputSchema, dashboardAttributesSchema } from './v2';
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
import { Serializable } from '@kbn/utility-types';
|
||||
import { TypeOf } from '@kbn/config-schema';
|
||||
import { dashboardAttributesSchema, gridDataSchema, sectionSchema } from './v2';
|
||||
import { dashboardAttributesSchema, gridDataSchema } from './v2';
|
||||
|
||||
export type DashboardAttributes = TypeOf<typeof dashboardAttributesSchema>;
|
||||
export type GridData = TypeOf<typeof gridDataSchema>;
|
||||
|
@ -33,8 +33,3 @@ export interface SavedDashboardPanel {
|
|||
*/
|
||||
version?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A saved dashboard section parsed directly from the Dashboard Attributes
|
||||
*/
|
||||
export type SavedDashboardSection = TypeOf<typeof sectionSchema>;
|
||||
|
|
|
@ -13,26 +13,6 @@ import {
|
|||
dashboardAttributesSchema as dashboardAttributesSchemaV1,
|
||||
} from '../v1';
|
||||
|
||||
// sections only include y + i for grid data
|
||||
export const sectionGridDataSchema = schema.object({
|
||||
y: schema.number(),
|
||||
i: schema.string(),
|
||||
});
|
||||
|
||||
// panels include all grid data keys, including those that sections use
|
||||
export const gridDataSchema = sectionGridDataSchema.extends({
|
||||
x: schema.number(),
|
||||
w: schema.number(),
|
||||
h: schema.number(),
|
||||
sectionId: schema.maybe(schema.string()),
|
||||
});
|
||||
|
||||
export const sectionSchema = schema.object({
|
||||
title: schema.string(),
|
||||
collapsed: schema.maybe(schema.boolean()),
|
||||
gridData: sectionGridDataSchema,
|
||||
});
|
||||
|
||||
export const controlGroupInputSchema = controlGroupInputSchemaV1.extends(
|
||||
{
|
||||
showApplySelections: schema.maybe(schema.boolean()),
|
||||
|
@ -43,7 +23,14 @@ export const controlGroupInputSchema = controlGroupInputSchemaV1.extends(
|
|||
export const dashboardAttributesSchema = dashboardAttributesSchemaV1.extends(
|
||||
{
|
||||
controlGroupInput: schema.maybe(controlGroupInputSchema),
|
||||
sections: schema.maybe(schema.arrayOf(sectionSchema)),
|
||||
},
|
||||
{ unknowns: 'ignore' }
|
||||
);
|
||||
|
||||
export const gridDataSchema = schema.object({
|
||||
x: schema.number(),
|
||||
y: schema.number(),
|
||||
w: schema.number(),
|
||||
h: schema.number(),
|
||||
i: schema.string(),
|
||||
});
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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".
|
||||
*/
|
||||
|
||||
export type {
|
||||
DashboardAttributes,
|
||||
GridData,
|
||||
SavedDashboardPanel,
|
||||
SavedDashboardSection,
|
||||
} from './types';
|
||||
export { dashboardAttributesSchema } from './v3';
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 { TypeOf } from '@kbn/config-schema';
|
||||
import { SavedDashboardPanel as SavedDashboardPanelV2 } from '../v2';
|
||||
import { dashboardAttributesSchema, gridDataSchema, sectionSchema } from './v3';
|
||||
|
||||
export type DashboardAttributes = TypeOf<typeof dashboardAttributesSchema>;
|
||||
export type GridData = TypeOf<typeof gridDataSchema>;
|
||||
|
||||
/**
|
||||
* A saved dashboard panel parsed directly from the Dashboard Attributes panels JSON
|
||||
*/
|
||||
export type SavedDashboardPanel = Omit<SavedDashboardPanelV2, 'gridData'> & { gridData: GridData };
|
||||
|
||||
/**
|
||||
* A saved dashboard section parsed directly from the Dashboard Attributes
|
||||
*/
|
||||
export type SavedDashboardSection = TypeOf<typeof sectionSchema>;
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
import { dashboardAttributesSchema as dashboardAttributesSchemaV2 } from '../v2';
|
||||
|
||||
// sections only include y + i for grid data
|
||||
export const sectionGridDataSchema = schema.object({
|
||||
y: schema.number(),
|
||||
i: schema.string(),
|
||||
});
|
||||
|
||||
// panels include all grid data keys, including those that sections use
|
||||
export const gridDataSchema = sectionGridDataSchema.extends({
|
||||
x: schema.number(),
|
||||
w: schema.number(),
|
||||
h: schema.number(),
|
||||
sectionId: schema.maybe(schema.string()),
|
||||
});
|
||||
|
||||
export const sectionSchema = schema.object({
|
||||
title: schema.string(),
|
||||
collapsed: schema.maybe(schema.boolean()),
|
||||
gridData: sectionGridDataSchema,
|
||||
});
|
||||
|
||||
export const dashboardAttributesSchema = dashboardAttributesSchemaV2.extends(
|
||||
{
|
||||
sections: schema.maybe(schema.arrayOf(sectionSchema)),
|
||||
},
|
||||
{ unknowns: 'ignore' }
|
||||
);
|
|
@ -234,10 +234,10 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
type: 'dashboard',
|
||||
namespaces: ['default'],
|
||||
migrationVersion: {
|
||||
dashboard: '10.2.0',
|
||||
dashboard: '10.3.0',
|
||||
},
|
||||
coreMigrationVersion: '8.8.0',
|
||||
typeMigrationVersion: '10.2.0',
|
||||
typeMigrationVersion: '10.3.0',
|
||||
updated_at: '2015-01-01T00:00:00.000Z',
|
||||
created_at: '2015-01-01T00:00:00.000Z',
|
||||
version: resp.body.saved_objects[3].version,
|
||||
|
|
|
@ -84,10 +84,10 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
type: 'dashboard',
|
||||
namespaces: ['default'],
|
||||
migrationVersion: {
|
||||
dashboard: '10.2.0',
|
||||
dashboard: '10.3.0',
|
||||
},
|
||||
coreMigrationVersion: '8.8.0',
|
||||
typeMigrationVersion: '10.2.0',
|
||||
typeMigrationVersion: '10.3.0',
|
||||
updated_at: resp.body.updated_at,
|
||||
created_at: resp.body.created_at,
|
||||
version: resp.body.version,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue