mirror of
https://github.com/apache/superset.git
synced 2026-04-19 16:14:52 +00:00
fix(ag-grid): fix conditional formatting theme colors and module extensibility (#35605)
This commit is contained in:
committed by
GitHub
parent
79918a7939
commit
5e4a80e5d0
@@ -241,10 +241,21 @@ export const getColorFormatters = memoizeOne(
|
|||||||
(
|
(
|
||||||
columnConfig: ConditionalFormattingConfig[] | undefined,
|
columnConfig: ConditionalFormattingConfig[] | undefined,
|
||||||
data: DataRecord[],
|
data: DataRecord[],
|
||||||
|
theme?: Record<string, any>,
|
||||||
alpha?: boolean,
|
alpha?: boolean,
|
||||||
) =>
|
) =>
|
||||||
columnConfig?.reduce(
|
columnConfig?.reduce(
|
||||||
(acc: ColorFormatters, config: ConditionalFormattingConfig) => {
|
(acc: ColorFormatters, config: ConditionalFormattingConfig) => {
|
||||||
|
let resolvedColorScheme = config.colorScheme;
|
||||||
|
if (
|
||||||
|
theme &&
|
||||||
|
typeof config.colorScheme === 'string' &&
|
||||||
|
config.colorScheme.startsWith('color') &&
|
||||||
|
theme[config.colorScheme]
|
||||||
|
) {
|
||||||
|
resolvedColorScheme = theme[config.colorScheme] as string;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
config?.column !== undefined &&
|
config?.column !== undefined &&
|
||||||
(config?.operator === Comparator.None ||
|
(config?.operator === Comparator.None ||
|
||||||
@@ -257,7 +268,7 @@ export const getColorFormatters = memoizeOne(
|
|||||||
acc.push({
|
acc.push({
|
||||||
column: config?.column,
|
column: config?.column,
|
||||||
getColorFromValue: getColorFunction(
|
getColorFromValue: getColorFunction(
|
||||||
config,
|
{ ...config, colorScheme: resolvedColorScheme },
|
||||||
data.map(row => row[config.column!] as number),
|
data.map(row => row[config.column!] as number),
|
||||||
alpha,
|
alpha,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -218,3 +218,29 @@ test('handles missing theme gracefully', () => {
|
|||||||
// Should still render without crashing
|
// Should still render without crashing
|
||||||
expect(screen.getByTestId('ag-grid-react')).toBeInTheDocument();
|
expect(screen.getByTestId('ag-grid-react')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('merges theme overrides with default theme parameters', () => {
|
||||||
|
const themeOverrides = {
|
||||||
|
fontSize: 16,
|
||||||
|
headerBackgroundColor: '#custom-color',
|
||||||
|
};
|
||||||
|
|
||||||
|
render(
|
||||||
|
<ThemedAgGridReact
|
||||||
|
rowData={mockRowData}
|
||||||
|
columnDefs={mockColumnDefs}
|
||||||
|
themeOverrides={themeOverrides}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const agGrid = screen.getByTestId('ag-grid-react');
|
||||||
|
const theme = JSON.parse(agGrid.getAttribute('data-theme') || '{}');
|
||||||
|
|
||||||
|
// Custom overrides should be applied
|
||||||
|
expect(theme.fontSize).toBe(16);
|
||||||
|
expect(theme.headerBackgroundColor).toBe('#custom-color');
|
||||||
|
|
||||||
|
// Default theme parameters should still be present
|
||||||
|
expect(theme.foregroundColor).toBeDefined();
|
||||||
|
expect(theme.borderColor).toBeDefined();
|
||||||
|
});
|
||||||
|
|||||||
@@ -186,5 +186,5 @@ export {
|
|||||||
// Re-export AgGridReact for ref types
|
// Re-export AgGridReact for ref types
|
||||||
export { AgGridReact } from 'ag-grid-react';
|
export { AgGridReact } from 'ag-grid-react';
|
||||||
|
|
||||||
// Export the setup function for AG-Grid modules
|
// Export the setup function and default modules for AG-Grid
|
||||||
export { setupAGGridModules } from './setupAGGridModules';
|
export { setupAGGridModules, defaultModules } from './setupAGGridModules';
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { ModuleRegistry } from 'ag-grid-community';
|
||||||
|
import { setupAGGridModules, defaultModules } from './setupAGGridModules';
|
||||||
|
|
||||||
|
jest.mock('ag-grid-community', () => ({
|
||||||
|
ModuleRegistry: {
|
||||||
|
registerModules: jest.fn(),
|
||||||
|
},
|
||||||
|
ColumnAutoSizeModule: { moduleName: 'ColumnAutoSizeModule' },
|
||||||
|
ColumnHoverModule: { moduleName: 'ColumnHoverModule' },
|
||||||
|
RowAutoHeightModule: { moduleName: 'RowAutoHeightModule' },
|
||||||
|
RowStyleModule: { moduleName: 'RowStyleModule' },
|
||||||
|
PaginationModule: { moduleName: 'PaginationModule' },
|
||||||
|
CellStyleModule: { moduleName: 'CellStyleModule' },
|
||||||
|
TextFilterModule: { moduleName: 'TextFilterModule' },
|
||||||
|
NumberFilterModule: { moduleName: 'NumberFilterModule' },
|
||||||
|
DateFilterModule: { moduleName: 'DateFilterModule' },
|
||||||
|
ExternalFilterModule: { moduleName: 'ExternalFilterModule' },
|
||||||
|
CsvExportModule: { moduleName: 'CsvExportModule' },
|
||||||
|
ColumnApiModule: { moduleName: 'ColumnApiModule' },
|
||||||
|
RowApiModule: { moduleName: 'RowApiModule' },
|
||||||
|
CellApiModule: { moduleName: 'CellApiModule' },
|
||||||
|
RenderApiModule: { moduleName: 'RenderApiModule' },
|
||||||
|
ClientSideRowModelModule: { moduleName: 'ClientSideRowModelModule' },
|
||||||
|
CustomFilterModule: { moduleName: 'CustomFilterModule' },
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('defaultModules exports an array of AG Grid modules', () => {
|
||||||
|
expect(Array.isArray(defaultModules)).toBe(true);
|
||||||
|
expect(defaultModules.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
// Verify it contains expected modules
|
||||||
|
const moduleNames = defaultModules.map((m: any) => m.moduleName);
|
||||||
|
expect(moduleNames).toContain('ColumnAutoSizeModule');
|
||||||
|
expect(moduleNames).toContain('PaginationModule');
|
||||||
|
expect(moduleNames).toContain('ClientSideRowModelModule');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setupAGGridModules registers default modules when called without arguments', () => {
|
||||||
|
setupAGGridModules();
|
||||||
|
|
||||||
|
expect(ModuleRegistry.registerModules).toHaveBeenCalledTimes(1);
|
||||||
|
expect(ModuleRegistry.registerModules).toHaveBeenCalledWith(defaultModules);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setupAGGridModules registers default + additional modules when provided', () => {
|
||||||
|
const mockEnterpriseModule1 = { moduleName: 'MultiFilterModule' };
|
||||||
|
const mockEnterpriseModule2 = { moduleName: 'PivotModule' };
|
||||||
|
const additionalModules = [mockEnterpriseModule1, mockEnterpriseModule2];
|
||||||
|
|
||||||
|
setupAGGridModules(additionalModules);
|
||||||
|
|
||||||
|
expect(ModuleRegistry.registerModules).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
const registeredModules = (ModuleRegistry.registerModules as jest.Mock).mock
|
||||||
|
.calls[0][0];
|
||||||
|
|
||||||
|
// Should contain all default modules
|
||||||
|
defaultModules.forEach(module => {
|
||||||
|
expect(registeredModules).toContain(module);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Should contain additional modules
|
||||||
|
expect(registeredModules).toContain(mockEnterpriseModule1);
|
||||||
|
expect(registeredModules).toContain(mockEnterpriseModule2);
|
||||||
|
|
||||||
|
// Total length should be default + additional
|
||||||
|
expect(registeredModules.length).toBe(
|
||||||
|
defaultModules.length + additionalModules.length,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setupAGGridModules handles empty additional modules array', () => {
|
||||||
|
setupAGGridModules([]);
|
||||||
|
|
||||||
|
expect(ModuleRegistry.registerModules).toHaveBeenCalledTimes(1);
|
||||||
|
expect(ModuleRegistry.registerModules).toHaveBeenCalledWith(defaultModules);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setupAGGridModules does not mutate defaultModules array', () => {
|
||||||
|
const originalLength = defaultModules.length;
|
||||||
|
const mockEnterpriseModule = { moduleName: 'EnterpriseModule' };
|
||||||
|
|
||||||
|
setupAGGridModules([mockEnterpriseModule]);
|
||||||
|
|
||||||
|
// defaultModules should remain unchanged
|
||||||
|
expect(defaultModules.length).toBe(originalLength);
|
||||||
|
expect(defaultModules).not.toContain(mockEnterpriseModule);
|
||||||
|
});
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
ModuleRegistry,
|
ModuleRegistry,
|
||||||
|
type Module,
|
||||||
ColumnAutoSizeModule,
|
ColumnAutoSizeModule,
|
||||||
ColumnHoverModule,
|
ColumnHoverModule,
|
||||||
RowAutoHeightModule,
|
RowAutoHeightModule,
|
||||||
@@ -39,27 +40,29 @@ import {
|
|||||||
} from 'ag-grid-community';
|
} from 'ag-grid-community';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the AG-Grid modules required for Superset's table functionality.
|
* Default AG Grid modules that are registered by default.
|
||||||
* This should be called once during application initialization.
|
* These modules provide core AG Grid functionality.
|
||||||
*/
|
*/
|
||||||
export const setupAGGridModules = () => {
|
export const defaultModules: Module[] = [
|
||||||
ModuleRegistry.registerModules([
|
ColumnAutoSizeModule,
|
||||||
ColumnAutoSizeModule,
|
ColumnHoverModule,
|
||||||
ColumnHoverModule,
|
RowAutoHeightModule,
|
||||||
RowAutoHeightModule,
|
RowStyleModule,
|
||||||
RowStyleModule,
|
PaginationModule,
|
||||||
PaginationModule,
|
CellStyleModule,
|
||||||
CellStyleModule,
|
TextFilterModule,
|
||||||
TextFilterModule,
|
NumberFilterModule,
|
||||||
NumberFilterModule,
|
DateFilterModule,
|
||||||
DateFilterModule,
|
ExternalFilterModule,
|
||||||
ExternalFilterModule,
|
CsvExportModule,
|
||||||
CsvExportModule,
|
ColumnApiModule,
|
||||||
ColumnApiModule,
|
RowApiModule,
|
||||||
RowApiModule,
|
CellApiModule,
|
||||||
CellApiModule,
|
RenderApiModule,
|
||||||
RenderApiModule,
|
ClientSideRowModelModule,
|
||||||
ClientSideRowModelModule,
|
CustomFilterModule,
|
||||||
CustomFilterModule,
|
];
|
||||||
]);
|
|
||||||
|
export const setupAGGridModules = (additionalModules: Module[] = []) => {
|
||||||
|
ModuleRegistry.registerModules([...defaultModules, ...additionalModules]);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ export {
|
|||||||
ThemedAgGridReact,
|
ThemedAgGridReact,
|
||||||
type ThemedAgGridReactProps,
|
type ThemedAgGridReactProps,
|
||||||
setupAGGridModules,
|
setupAGGridModules,
|
||||||
|
defaultModules,
|
||||||
} from './ThemedAgGridReact';
|
} from './ThemedAgGridReact';
|
||||||
export {
|
export {
|
||||||
CodeEditor,
|
CodeEditor,
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 51 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 16 KiB |
@@ -74,6 +74,23 @@ function isPositiveNumber(value: string | number | null | undefined) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const calculateDifferences = (
|
||||||
|
originalValue: number,
|
||||||
|
comparisonValue: number,
|
||||||
|
) => {
|
||||||
|
const valueDifference = originalValue - comparisonValue;
|
||||||
|
let percentDifferenceNum;
|
||||||
|
if (!originalValue && !comparisonValue) {
|
||||||
|
percentDifferenceNum = 0;
|
||||||
|
} else if (!originalValue || !comparisonValue) {
|
||||||
|
percentDifferenceNum = originalValue ? 1 : -1;
|
||||||
|
} else {
|
||||||
|
percentDifferenceNum =
|
||||||
|
(originalValue - comparisonValue) / Math.abs(comparisonValue);
|
||||||
|
}
|
||||||
|
return { valueDifference, percentDifferenceNum };
|
||||||
|
};
|
||||||
|
|
||||||
const processComparisonTotals = (
|
const processComparisonTotals = (
|
||||||
comparisonSuffix: string,
|
comparisonSuffix: string,
|
||||||
totals?: DataRecord[],
|
totals?: DataRecord[],
|
||||||
@@ -149,23 +166,6 @@ const getComparisonColFormatter = (
|
|||||||
return formatter;
|
return formatter;
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateDifferences = (
|
|
||||||
originalValue: number,
|
|
||||||
comparisonValue: number,
|
|
||||||
) => {
|
|
||||||
const valueDifference = originalValue - comparisonValue;
|
|
||||||
let percentDifferenceNum;
|
|
||||||
if (!originalValue && !comparisonValue) {
|
|
||||||
percentDifferenceNum = 0;
|
|
||||||
} else if (!originalValue || !comparisonValue) {
|
|
||||||
percentDifferenceNum = originalValue ? 1 : -1;
|
|
||||||
} else {
|
|
||||||
percentDifferenceNum =
|
|
||||||
(originalValue - comparisonValue) / Math.abs(comparisonValue);
|
|
||||||
}
|
|
||||||
return { valueDifference, percentDifferenceNum };
|
|
||||||
};
|
|
||||||
|
|
||||||
const processComparisonDataRecords = memoizeOne(
|
const processComparisonDataRecords = memoizeOne(
|
||||||
function processComparisonDataRecords(
|
function processComparisonDataRecords(
|
||||||
originalData: DataRecord[] | undefined,
|
originalData: DataRecord[] | undefined,
|
||||||
@@ -471,6 +471,7 @@ const transformProps = (
|
|||||||
filterState,
|
filterState,
|
||||||
hooks: { setDataMask = () => {} },
|
hooks: { setDataMask = () => {} },
|
||||||
emitCrossFilters,
|
emitCrossFilters,
|
||||||
|
theme,
|
||||||
} = chartProps;
|
} = chartProps;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -494,6 +495,36 @@ const transformProps = (
|
|||||||
|
|
||||||
const allowRearrangeColumns = true;
|
const allowRearrangeColumns = true;
|
||||||
|
|
||||||
|
// Calculate time comparison settings early since they're used in multiple places
|
||||||
|
const isUsingTimeComparison =
|
||||||
|
!isEmpty(time_compare) &&
|
||||||
|
queryMode === QueryMode.Aggregate &&
|
||||||
|
comparison_type === ComparisonType.Values &&
|
||||||
|
isFeatureEnabled(FeatureFlag.TableV2TimeComparisonEnabled);
|
||||||
|
|
||||||
|
const nonCustomNorInheritShifts = ensureIsArray(formData.time_compare).filter(
|
||||||
|
(shift: string) => shift !== 'custom' && shift !== 'inherit',
|
||||||
|
);
|
||||||
|
const customOrInheritShifts = ensureIsArray(formData.time_compare).filter(
|
||||||
|
(shift: string) => shift === 'custom' || shift === 'inherit',
|
||||||
|
);
|
||||||
|
|
||||||
|
let timeOffsets: string[] = [];
|
||||||
|
|
||||||
|
if (isUsingTimeComparison && !isEmpty(nonCustomNorInheritShifts)) {
|
||||||
|
timeOffsets = nonCustomNorInheritShifts;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shifts for custom or inherit time comparison
|
||||||
|
if (isUsingTimeComparison && !isEmpty(customOrInheritShifts)) {
|
||||||
|
if (customOrInheritShifts.includes('custom')) {
|
||||||
|
timeOffsets = timeOffsets.concat([formData.start_date_offset]);
|
||||||
|
}
|
||||||
|
if (customOrInheritShifts.includes('inherit')) {
|
||||||
|
timeOffsets = timeOffsets.concat(['inherit']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const calculateBasicStyle = (
|
const calculateBasicStyle = (
|
||||||
percentDifferenceNum: number,
|
percentDifferenceNum: number,
|
||||||
colorOption: ColorSchemeEnum,
|
colorOption: ColorSchemeEnum,
|
||||||
@@ -606,12 +637,6 @@ const transformProps = (
|
|||||||
: undefined;
|
: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isUsingTimeComparison =
|
|
||||||
!isEmpty(time_compare) &&
|
|
||||||
queryMode === QueryMode.Aggregate &&
|
|
||||||
comparison_type === ComparisonType.Values &&
|
|
||||||
isFeatureEnabled(FeatureFlag.TableV2TimeComparisonEnabled);
|
|
||||||
|
|
||||||
let hasServerPageLengthChanged = false;
|
let hasServerPageLengthChanged = false;
|
||||||
|
|
||||||
const pageLengthFromMap = serverPageLengthMap.get(slice_id);
|
const pageLengthFromMap = serverPageLengthMap.get(slice_id);
|
||||||
@@ -624,28 +649,6 @@ const transformProps = (
|
|||||||
|
|
||||||
const timeGrain = extractTimegrain(formData);
|
const timeGrain = extractTimegrain(formData);
|
||||||
|
|
||||||
const nonCustomNorInheritShifts = ensureIsArray(formData.time_compare).filter(
|
|
||||||
(shift: string) => shift !== 'custom' && shift !== 'inherit',
|
|
||||||
);
|
|
||||||
const customOrInheritShifts = ensureIsArray(formData.time_compare).filter(
|
|
||||||
(shift: string) => shift === 'custom' || shift === 'inherit',
|
|
||||||
);
|
|
||||||
|
|
||||||
let timeOffsets: string[] = [];
|
|
||||||
|
|
||||||
if (isUsingTimeComparison && !isEmpty(nonCustomNorInheritShifts)) {
|
|
||||||
timeOffsets = nonCustomNorInheritShifts;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shifts for custom or inherit time comparison
|
|
||||||
if (isUsingTimeComparison && !isEmpty(customOrInheritShifts)) {
|
|
||||||
if (customOrInheritShifts.includes('custom')) {
|
|
||||||
timeOffsets = timeOffsets.concat([formData.start_date_offset]);
|
|
||||||
}
|
|
||||||
if (customOrInheritShifts.includes('inherit')) {
|
|
||||||
timeOffsets = timeOffsets.concat(['inherit']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const comparisonSuffix = isUsingTimeComparison
|
const comparisonSuffix = isUsingTimeComparison
|
||||||
? ensureIsArray(timeOffsets)[0]
|
? ensureIsArray(timeOffsets)[0]
|
||||||
: '';
|
: '';
|
||||||
@@ -685,7 +688,7 @@ const transformProps = (
|
|||||||
const basicColorFormatters =
|
const basicColorFormatters =
|
||||||
comparisonColorEnabled && getBasicColorFormatter(baseQuery?.data, columns);
|
comparisonColorEnabled && getBasicColorFormatter(baseQuery?.data, columns);
|
||||||
const columnColorFormatters =
|
const columnColorFormatters =
|
||||||
getColorFormatters(conditionalFormatting, passedData) ?? [];
|
getColorFormatters(conditionalFormatting, passedData, theme) ?? [];
|
||||||
|
|
||||||
const basicColorColumnFormatters = getBasicColorFormatterForColumn(
|
const basicColorColumnFormatters = getBasicColorFormatterForColumn(
|
||||||
baseQuery?.data,
|
baseQuery?.data,
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export default function transformProps(
|
|||||||
rawFormData,
|
rawFormData,
|
||||||
hooks,
|
hooks,
|
||||||
datasource: { currencyFormats = {}, columnFormats = {} },
|
datasource: { currencyFormats = {}, columnFormats = {} },
|
||||||
|
theme,
|
||||||
} = chartProps;
|
} = chartProps;
|
||||||
const {
|
const {
|
||||||
metricNameFontSize,
|
metricNameFontSize,
|
||||||
@@ -105,7 +106,7 @@ export default function transformProps(
|
|||||||
const defaultColorFormatters = [] as ColorFormatters;
|
const defaultColorFormatters = [] as ColorFormatters;
|
||||||
|
|
||||||
const colorThresholdFormatters =
|
const colorThresholdFormatters =
|
||||||
getColorFormatters(conditionalFormatting, data, false) ??
|
getColorFormatters(conditionalFormatting, data, theme, false) ??
|
||||||
defaultColorFormatters;
|
defaultColorFormatters;
|
||||||
return {
|
return {
|
||||||
width,
|
width,
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ export default function transformProps(chartProps: ChartProps<QueryFormData>) {
|
|||||||
filterState,
|
filterState,
|
||||||
datasource: { verboseMap = {}, columnFormats = {}, currencyFormats = {} },
|
datasource: { verboseMap = {}, columnFormats = {}, currencyFormats = {} },
|
||||||
emitCrossFilters,
|
emitCrossFilters,
|
||||||
|
theme,
|
||||||
} = chartProps;
|
} = chartProps;
|
||||||
const { data, colnames, coltypes } = queriesData[0];
|
const { data, colnames, coltypes } = queriesData[0];
|
||||||
const {
|
const {
|
||||||
@@ -141,7 +142,11 @@ export default function transformProps(chartProps: ChartProps<QueryFormData>) {
|
|||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
const metricColorFormatters = getColorFormatters(conditionalFormatting, data);
|
const metricColorFormatters = getColorFormatters(
|
||||||
|
conditionalFormatting,
|
||||||
|
data,
|
||||||
|
theme,
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
width,
|
width,
|
||||||
|
|||||||
@@ -469,6 +469,7 @@ const transformProps = (
|
|||||||
onContextMenu,
|
onContextMenu,
|
||||||
},
|
},
|
||||||
emitCrossFilters,
|
emitCrossFilters,
|
||||||
|
theme,
|
||||||
} = chartProps;
|
} = chartProps;
|
||||||
|
|
||||||
const formData = merge(
|
const formData = merge(
|
||||||
@@ -682,7 +683,7 @@ const transformProps = (
|
|||||||
const basicColorFormatters =
|
const basicColorFormatters =
|
||||||
comparisonColorEnabled && getBasicColorFormatter(baseQuery?.data, columns);
|
comparisonColorEnabled && getBasicColorFormatter(baseQuery?.data, columns);
|
||||||
const columnColorFormatters =
|
const columnColorFormatters =
|
||||||
getColorFormatters(conditionalFormatting, passedData) ??
|
getColorFormatters(conditionalFormatting, passedData, theme) ??
|
||||||
defaultColorFormatters;
|
defaultColorFormatters;
|
||||||
|
|
||||||
const basicColorColumnFormatters = getBasicColorFormatterForColumn(
|
const basicColorColumnFormatters = getBasicColorFormatterForColumn(
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export default memo(function ColumnConfigItem({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
right: 3 * sizeUnit,
|
right: 3 * sizeUnit,
|
||||||
top: 3 * sizeUnit,
|
top: 4 * sizeUnit,
|
||||||
transform: 'translateY(-50%)',
|
transform: 'translateY(-50%)',
|
||||||
gap: sizeUnit,
|
gap: sizeUnit,
|
||||||
color: theme.colorTextSecondary,
|
color: theme.colorTextSecondary,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { useMemo, useState, useEffect } from 'react';
|
import { useMemo, useState, useEffect } from 'react';
|
||||||
import { styled, SupersetTheme, t, useTheme } from '@superset-ui/core';
|
import { styled, t } from '@superset-ui/core';
|
||||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import {
|
import {
|
||||||
Comparator,
|
Comparator,
|
||||||
@@ -56,10 +56,11 @@ const JustifyEnd = styled.div`
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const colorSchemeOptions = (theme: SupersetTheme) => [
|
// Use theme token names instead of hex values to support theme switching
|
||||||
{ value: theme.colorSuccessBg, label: t('success') },
|
const colorSchemeOptions = () => [
|
||||||
{ value: theme.colorWarningBg, label: t('alert') },
|
{ value: 'colorSuccessBg', label: t('success') },
|
||||||
{ value: theme.colorErrorBg, label: t('error') },
|
{ value: 'colorWarningBg', label: t('alert') },
|
||||||
|
{ value: 'colorErrorBg', label: t('error') },
|
||||||
];
|
];
|
||||||
|
|
||||||
const operatorOptions = [
|
const operatorOptions = [
|
||||||
@@ -238,9 +239,8 @@ export const FormattingPopoverContent = ({
|
|||||||
columns: { label: string; value: string; dataType: GenericDataType }[];
|
columns: { label: string; value: string; dataType: GenericDataType }[];
|
||||||
extraColorChoices?: { label: string; value: string }[];
|
extraColorChoices?: { label: string; value: string }[];
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const colorScheme = colorSchemeOptions(theme);
|
const colorScheme = colorSchemeOptions();
|
||||||
const [showOperatorFields, setShowOperatorFields] = useState(
|
const [showOperatorFields, setShowOperatorFields] = useState(
|
||||||
config === undefined ||
|
config === undefined ||
|
||||||
(config?.colorScheme !== ColorSchemeEnum.Green &&
|
(config?.colorScheme !== ColorSchemeEnum.Green &&
|
||||||
|
|||||||
Reference in New Issue
Block a user