diff --git a/src/plugins/dashboard/common/content_management/constants.ts b/src/plugins/dashboard/common/content_management/constants.ts
index e235cb43d6357..978271680af12 100644
--- a/src/plugins/dashboard/common/content_management/constants.ts
+++ b/src/plugins/dashboard/common/content_management/constants.ts
@@ -18,9 +18,6 @@ export const DEFAULT_PANEL_HEIGHT = 15;
export const DEFAULT_DASHBOARD_OPTIONS = {
hidePanelTitles: false,
useMargins: true,
- /**
- * @deprecated https://github.com/elastic/kibana/pull/197802
- **/
syncColors: true,
syncCursor: true,
syncTooltips: true,
diff --git a/src/plugins/dashboard/common/dashboard_container/types.ts b/src/plugins/dashboard/common/dashboard_container/types.ts
index cf8c6b02e550e..dd3f7302038c0 100644
--- a/src/plugins/dashboard/common/dashboard_container/types.ts
+++ b/src/plugins/dashboard/common/dashboard_container/types.ts
@@ -64,9 +64,6 @@ export interface DashboardContainerInput extends EmbeddableInput {
hidePanelTitles: DashboardOptions['hidePanelTitles'];
syncTooltips: DashboardOptions['syncTooltips'];
useMargins: DashboardOptions['useMargins'];
- /**
- * @deprecated https://github.com/elastic/kibana/pull/197802
- **/
syncColors: DashboardOptions['syncColors'];
syncCursor: DashboardOptions['syncCursor'];
diff --git a/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx b/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx
index 76617866ca3f1..20fd2b93119de 100644
--- a/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx
+++ b/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx
@@ -22,7 +22,9 @@ import {
EuiFlyoutHeader,
EuiForm,
EuiFormRow,
+ EuiIconTip,
EuiSwitch,
+ EuiText,
EuiTextArea,
EuiTitle,
} from '@elastic/eui';
@@ -265,6 +267,54 @@ export const DashboardSettings = ({ onClose }: DashboardSettingsProps) => {
)}
>
<>
+
+
+ {i18n.translate(
+ 'dashboard.embeddableApi.showSettings.flyout.form.syncColorsBetweenPanelsSwitchLabel',
+ {
+ defaultMessage: 'Sync color palettes across panels',
+ }
+ )}{' '}
+
+ {i18n.translate('dashboard.palettes.defaultPaletteLabel', {
+ defaultMessage: 'Default',
+ })}
+
+ ),
+ compatibility: (
+
+ {i18n.translate('dashboard.palettes.kibanaPaletteLabel', {
+ defaultMessage: 'Compatibility',
+ })}
+
+ ),
+ }}
+ />
+ }
+ iconProps={{
+ className: 'eui-alignTop',
+ }}
+ position="top"
+ size="s"
+ type="questionInCircle"
+ />
+
+ }
+ checked={localSettings.syncColors}
+ onChange={(event) => updateDashboardSetting({ syncColors: event.target.checked })}
+ data-test-subj="dashboardSyncColorsCheckbox"
+ />
+
{
timeslice: [number, number];
};
expect(embeddableInput.syncTooltips).toBe(false);
+ expect(embeddableInput.syncColors).toBe(false);
expect(embeddableInput.syncCursor).toBe(true);
});
});
diff --git a/src/plugins/dashboard/server/content_management/v3/cm_services.ts b/src/plugins/dashboard/server/content_management/v3/cm_services.ts
index 88f3599e3224b..e086d1cc1460a 100644
--- a/src/plugins/dashboard/server/content_management/v3/cm_services.ts
+++ b/src/plugins/dashboard/server/content_management/v3/cm_services.ts
@@ -309,16 +309,9 @@ export const optionsSchema = schema.object({
defaultValue: DEFAULT_DASHBOARD_OPTIONS.useMargins,
meta: { description: 'Show margins between panels in the dashboard layout.' },
}),
- /**
- * @deprecated https://github.com/elastic/kibana/pull/197802
- **/
syncColors: schema.boolean({
defaultValue: DEFAULT_DASHBOARD_OPTIONS.syncColors,
- meta: {
- deprecated: true,
- description:
- 'Previously used to synchronize legacy colors between related panels in the dashboard.',
- },
+ meta: { description: 'Synchronize colors between related panels in the dashboard.' },
}),
syncTooltips: schema.boolean({
defaultValue: DEFAULT_DASHBOARD_OPTIONS.syncTooltips,
diff --git a/src/plugins/embeddable/common/types.ts b/src/plugins/embeddable/common/types.ts
index 40f38df545a8a..951ecd9026ded 100644
--- a/src/plugins/embeddable/common/types.ts
+++ b/src/plugins/embeddable/common/types.ts
@@ -57,9 +57,7 @@ export type EmbeddableInput = {
searchSessionId?: string;
/**
- * Flag whether legacy colors should be synced with other panels
- *
- * @deprecated https://github.com/elastic/kibana/pull/197802
+ * Flag whether colors should be synced with other panels
*/
syncColors?: boolean;
diff --git a/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts b/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts
index f59c808af0348..49f097f500a46 100644
--- a/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts
+++ b/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts
@@ -20,6 +20,7 @@ const getGenericEmbeddableState = (state?: Partial): Embeddable
disabledActions: [],
disableTriggers: false,
enhancements: undefined,
+ syncColors: false,
syncTooltips: false,
syncCursor: true,
viewMode: ViewMode.VIEW,
diff --git a/src/plugins/embeddable/public/store/input_slice.ts b/src/plugins/embeddable/public/store/input_slice.ts
index 6925cc85ae1c5..3b3cf8b8ee588 100644
--- a/src/plugins/embeddable/public/store/input_slice.ts
+++ b/src/plugins/embeddable/public/store/input_slice.ts
@@ -38,9 +38,6 @@ export const input = createSlice({
setSearchSessionId(state, action: PayloadAction) {
state.searchSessionId = action.payload;
},
- /**
- * @deprecated https://github.com/elastic/kibana/pull/197802
- **/
setSyncColors(state, action: PayloadAction) {
state.syncColors = action.payload;
},
diff --git a/src/plugins/expressions/public/types/index.ts b/src/plugins/expressions/public/types/index.ts
index bac67b5309699..2eb881e0a2bdd 100644
--- a/src/plugins/expressions/public/types/index.ts
+++ b/src/plugins/expressions/public/types/index.ts
@@ -49,9 +49,6 @@ export interface IExpressionLoaderParams {
onRenderError?: RenderErrorHandlerFnType;
searchSessionId?: string;
renderMode?: RenderMode;
- /**
- * @deprecated https://github.com/elastic/kibana/pull/197802
- **/
syncColors?: boolean;
syncCursor?: boolean;
syncTooltips?: boolean;
diff --git a/src/plugins/visualizations/public/legacy/embeddable/visualize_embeddable.tsx b/src/plugins/visualizations/public/legacy/embeddable/visualize_embeddable.tsx
index 2155a2457b766..196753d73b28c 100644
--- a/src/plugins/visualizations/public/legacy/embeddable/visualize_embeddable.tsx
+++ b/src/plugins/visualizations/public/legacy/embeddable/visualize_embeddable.tsx
@@ -108,9 +108,6 @@ export class VisualizeEmbeddable
private query?: Query;
private filters?: Filter[];
private searchSessionId?: string;
- /**
- * @deprecated https://github.com/elastic/kibana/pull/197802
- **/
private syncColors?: boolean;
private syncTooltips?: boolean;
private syncCursor?: boolean;
diff --git a/test/functional/services/dashboard/dashboard_settings.ts b/test/functional/services/dashboard/dashboard_settings.ts
index 60f23d9c02f41..b0c2f6d691b8e 100644
--- a/test/functional/services/dashboard/dashboard_settings.ts
+++ b/test/functional/services/dashboard/dashboard_settings.ts
@@ -77,6 +77,12 @@ export function DashboardSettingsProvider({ getService }: FtrProviderContext) {
await testSubjects.setEuiSwitch('dashboardPanelTitlesCheckbox', status);
}
+ public async toggleSyncColors(value: boolean) {
+ const status = value ? 'check' : 'uncheck';
+ log.debug(`toggleSyncColors::${status}`);
+ await testSubjects.setEuiSwitch('dashboardSyncColorsCheckbox', status);
+ }
+
public async toggleSyncCursor(value: boolean) {
const status = value ? 'check' : 'uncheck';
log.debug(`toggleSyncCursor::${status}`);
diff --git a/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx b/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx
index a53cb5a9475c9..d16df5bf9d1e8 100644
--- a/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx
+++ b/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx
@@ -33,9 +33,6 @@ export interface ExpressionWrapperProps {
) => void;
onRender$: () => void;
renderMode?: RenderMode;
- /**
- * @deprecated https://github.com/elastic/kibana/pull/197802
- **/
syncColors?: boolean;
syncTooltips?: boolean;
syncCursor?: boolean;
diff --git a/x-pack/test/functional/apps/dashboard/group2/index.ts b/x-pack/test/functional/apps/dashboard/group2/index.ts
index c2431a8e86c45..a233126f6e4a6 100644
--- a/x-pack/test/functional/apps/dashboard/group2/index.ts
+++ b/x-pack/test/functional/apps/dashboard/group2/index.ts
@@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('dashboard', function () {
+ loadTestFile(require.resolve('./sync_colors'));
loadTestFile(require.resolve('./_async_dashboard'));
loadTestFile(require.resolve('./dashboard_lens_by_value'));
loadTestFile(require.resolve('./dashboard_maps_by_value'));
diff --git a/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts b/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts
new file mode 100644
index 0000000000000..a89f35d917130
--- /dev/null
+++ b/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts
@@ -0,0 +1,162 @@
+/*
+ * 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; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { DebugState } from '@elastic/charts';
+import expect from '@kbn/expect';
+import chroma from 'chroma-js';
+import { FtrProviderContext } from '../../../ftr_provider_context';
+
+export default function ({ getService, getPageObjects }: FtrProviderContext) {
+ const esArchiver = getService('esArchiver');
+ const { dashboard, header, lens } = getPageObjects(['dashboard', 'header', 'lens']);
+ const dashboardAddPanel = getService('dashboardAddPanel');
+ const dashboardSettings = getService('dashboardSettings');
+ const filterBar = getService('filterBar');
+ const elasticChart = getService('elasticChart');
+ const kibanaServer = getService('kibanaServer');
+
+ function getColorMapping(debugState: DebugState | null) {
+ if (!debugState) return {};
+ const colorMapping: Record = {};
+ debugState.bars?.forEach(({ name, color }) => {
+ colorMapping[name] = color;
+ });
+
+ return colorMapping;
+ }
+
+ describe('sync colors', function () {
+ before(async function () {
+ await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional');
+ await kibanaServer.importExport.load(
+ 'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json'
+ );
+ });
+
+ after(async function () {
+ await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional');
+ await kibanaServer.importExport.unload(
+ 'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json'
+ );
+ await kibanaServer.savedObjects.cleanStandardList();
+ });
+
+ it('should sync colors on dashboard for legacy default palette', async function () {
+ await dashboard.navigateToApp();
+ await elasticChart.setNewChartUiDebugFlag(true);
+ await dashboard.clickCreateDashboardPrompt();
+
+ // create non-filtered xy chart
+ await dashboardAddPanel.clickCreateNewLink();
+ await lens.goToTimeRange();
+ await lens.configureDimension({
+ dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension',
+ operation: 'count',
+ field: 'Records',
+ });
+ await lens.configureDimension({
+ dimension: 'lnsXY_splitDimensionPanel > lns-empty-dimension',
+ operation: 'terms',
+ field: 'geo.src',
+ palette: { mode: 'legacy', id: 'default' },
+ });
+ await lens.saveAndReturn();
+ await header.waitUntilLoadingHasFinished();
+
+ // create filtered xy chart
+ await dashboardAddPanel.clickCreateNewLink();
+ await lens.configureDimension({
+ dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension',
+ operation: 'count',
+ field: 'Records',
+ });
+ await lens.configureDimension({
+ dimension: 'lnsXY_splitDimensionPanel > lns-empty-dimension',
+ operation: 'terms',
+ field: 'geo.src',
+ palette: { mode: 'legacy', id: 'default' },
+ });
+ await filterBar.addFilter({ field: 'geo.src', operation: 'is not', value: 'CN' });
+ await lens.saveAndReturn();
+ await header.waitUntilLoadingHasFinished();
+
+ // create datatable vis
+ await dashboardAddPanel.clickCreateNewLink();
+ await lens.switchToVisualization('lnsDatatable');
+ await lens.configureDimension({
+ dimension: 'lnsDatatable_rows > lns-empty-dimension',
+ operation: 'terms',
+ field: 'geo.src',
+ keepOpen: true,
+ });
+ await lens.setTermsNumberOfValues(5);
+ await lens.setTableDynamicColoring('cell');
+ await lens.setPalette('default', true);
+ await lens.closeDimensionEditor();
+ await lens.configureDimension({
+ dimension: 'lnsDatatable_metrics > lns-empty-dimension',
+ operation: 'count',
+ field: 'Records',
+ });
+ await lens.saveAndReturn();
+
+ // Set dashboard to sync colors
+ await dashboard.openSettingsFlyout();
+ await dashboardSettings.toggleSyncColors(true);
+ await dashboardSettings.clickApplyButton();
+ await header.waitUntilLoadingHasFinished();
+ await dashboard.waitForRenderComplete();
+
+ const colorMappings1 = Object.entries(
+ getColorMapping(await dashboard.getPanelChartDebugState(0))
+ );
+ const colorMappings2 = Object.entries(
+ getColorMapping(await dashboard.getPanelChartDebugState(1))
+ );
+
+ const els = await lens.getDatatableCellsByColumn(0);
+ const colorMappings3 = await Promise.all(
+ els.map(async (el) => [
+ await el.getVisibleText(),
+ chroma((await lens.getStylesFromCell(el))['background-color']).hex(), // eui converts hex to rgb
+ ])
+ );
+
+ expect(colorMappings1).to.have.length(6);
+ expect(colorMappings2).to.have.length(6);
+ expect(colorMappings3).to.have.length(6);
+
+ const mergedColorAssignments = new Map>();
+
+ [...colorMappings1, ...colorMappings2, ...colorMappings3].forEach(([key, color]) => {
+ if (!mergedColorAssignments.has(key)) mergedColorAssignments.set(key, new Set());
+ mergedColorAssignments.get(key)?.add(color);
+ });
+
+ // Each key should have only been assigned one color across all 3 visualizations
+ mergedColorAssignments.forEach((colors, key) => {
+ expect(colors.size).eql(
+ 1,
+ `Key "${key}" was assigned multiple colors: ${JSON.stringify([...colors])}`
+ );
+ });
+ });
+
+ it('should be possible to disable color sync', async () => {
+ await dashboard.openSettingsFlyout();
+ await dashboardSettings.toggleSyncColors(false);
+ await dashboardSettings.clickApplyButton();
+ await header.waitUntilLoadingHasFinished();
+ const colorMapping1 = getColorMapping(await dashboard.getPanelChartDebugState(0));
+ const colorMapping2 = getColorMapping(await dashboard.getPanelChartDebugState(1));
+ const colorsByOrder1 = Object.values(colorMapping1);
+ const colorsByOrder2 = Object.values(colorMapping2);
+ // colors by order of occurence have to be the same
+ expect(colorsByOrder1).to.eql(colorsByOrder2);
+ });
+ });
+}