From e319f42f5f81be6f4139d2d3a6ed6cc76861d299 Mon Sep 17 00:00:00 2001 From: Daria Larionova Date: Thu, 12 Dec 2024 16:28:54 +0300 Subject: [PATCH] Add nullMode to GradientColorConfig --- src/i18n-keysets/wizard/en.json | 2 + src/i18n-keysets/wizard/ru.json | 2 + ...kground-colors-map-by-continuous-column.ts | 25 +- .../datalens/preparers/flat-table/index.ts | 3 +- src/shared/constants/gradients/index.ts | 8 + src/shared/types/config/wizard/v12.ts | 3 +- src/shared/types/wizard/index.ts | 2 + src/ui/units/wizard/actions/dialogColor.ts | 4 +- .../ColorSettingsContainer.tsx | 1 + .../Dialogs/DialogColor/DialogColor.scss | 2 +- .../Dialogs/DialogColor/DialogColor.tsx | 11 +- .../DialogColorGradient.scss | 27 +-- .../DialogColorGradient.tsx | 216 ++++++++++-------- src/ui/units/wizard/constants/dialogColor.ts | 9 +- .../utils/clearUnusedVisualizationItems.ts | 16 +- src/ui/units/wizard/selectors/dialogColor.ts | 3 + 16 files changed, 193 insertions(+), 141 deletions(-) diff --git a/src/i18n-keysets/wizard/en.json b/src/i18n-keysets/wizard/en.json index 95dc2cc31f..3f1a40a6eb 100644 --- a/src/i18n-keysets/wizard/en.json +++ b/src/i18n-keysets/wizard/en.json @@ -226,6 +226,8 @@ "label_overlap": "Labels overlap", "label_overriden-from-dashboard": "overriden from dashboard", "label_pagination": "Pagination", + "label_painting-as-0": "Paint as 0", + "label_painting-ignore": "No painting", "label_palette": "Palette", "label_part": "Date part", "label_percent": "Percentage", diff --git a/src/i18n-keysets/wizard/ru.json b/src/i18n-keysets/wizard/ru.json index 26c36dc16d..d16eba7119 100644 --- a/src/i18n-keysets/wizard/ru.json +++ b/src/i18n-keysets/wizard/ru.json @@ -226,6 +226,8 @@ "label_overlap": "Перекрытие подписей", "label_overriden-from-dashboard": "перезаписан с дашборда", "label_pagination": "Пагинация", + "label_painting-as-0": "Окрашивать как 0", + "label_painting-ignore": "Не окрашивать", "label_palette": "Палитра", "label_part": "Часть даты", "label_percent": "В процентах", diff --git a/src/server/modes/charts/plugins/datalens/preparers/flat-table/helpers/background-settings/get-background-colors-map-by-continuous-column.ts b/src/server/modes/charts/plugins/datalens/preparers/flat-table/helpers/background-settings/get-background-colors-map-by-continuous-column.ts index ff36a0c25e..bc5f603f64 100644 --- a/src/server/modes/charts/plugins/datalens/preparers/flat-table/helpers/background-settings/get-background-colors-map-by-continuous-column.ts +++ b/src/server/modes/charts/plugins/datalens/preparers/flat-table/helpers/background-settings/get-background-colors-map-by-continuous-column.ts @@ -1,10 +1,11 @@ import isNil from 'lodash/isNil'; import isNumber from 'lodash/isNumber'; -import type { - RGBColor, - ServerField, - TableFieldBackgroundSettings, +import { + GradientNullModes, + type RGBColor, + type ServerField, + type TableFieldBackgroundSettings, } from '../../../../../../../../../shared'; import type {ChartColorsConfig} from '../../../../types'; import { @@ -46,15 +47,13 @@ export function colorizeFlatTableColumn({ index: number; colorsConfig: ChartColorsConfig; }) { - const colorValues = data.reduce( - (acc, row) => { - const rowValue = row[index]; - const parsedRowValue = isNil(rowValue) ? null : parseFloat(rowValue); - - return [...acc, parsedRowValue]; - }, - [] as (number | null)[], - ); + const nilValue = colorsConfig.nullMode === GradientNullModes.AsZero ? 0 : null; + const colorValues = data.reduce<(number | null)[]>((acc, row) => { + const rowValue = row[index]; + const parsedRowValue = isNil(rowValue) ? nilValue : parseFloat(rowValue); + acc.push(parsedRowValue); + return acc; + }, []); const {min, mid, max} = getThresholdValues(colorsConfig, colorValues.filter(isNumber)); const currentGradient = getCurrentGradient(colorsConfig); diff --git a/src/server/modes/charts/plugins/datalens/preparers/flat-table/index.ts b/src/server/modes/charts/plugins/datalens/preparers/flat-table/index.ts index eec53d17d4..326eca2b3e 100644 --- a/src/server/modes/charts/plugins/datalens/preparers/flat-table/index.ts +++ b/src/server/modes/charts/plugins/datalens/preparers/flat-table/index.ts @@ -7,6 +7,7 @@ import type { } from '../../../../../../../shared'; import { DATASET_FIELD_TYPES, + GradientNullModes, IS_NULL_FILTER_TEMPLATE, MINIMUM_FRACTION_DIGITS, isDateField, @@ -277,7 +278,7 @@ function prepareFlatTable({ if (colors.length) { const valueColor = values[iColor]; - if (valueColor !== null) { + if (valueColor !== null || colorsConfig.nullMode === GradientNullModes.AsZero) { cell.color = Number(valueColor); } } diff --git a/src/shared/constants/gradients/index.ts b/src/shared/constants/gradients/index.ts index 8b223cf25f..9ec8d6e65c 100644 --- a/src/shared/constants/gradients/index.ts +++ b/src/shared/constants/gradients/index.ts @@ -1,4 +1,5 @@ import type {ColorPalette} from '../../types/color-palettes'; +import type {ValueOf} from '../../types/utility-types'; import { THREE_POINT_DEFAULT_GRADIENT, @@ -27,6 +28,13 @@ export interface Gradient { colors: string[]; } +export const GradientNullModes = { + Ignore: 'ignore', + AsZero: 'as-0', +}; + +export type GradientNullMode = ValueOf; + export interface RGBColor { red: number; green: number; diff --git a/src/shared/types/config/wizard/v12.ts b/src/shared/types/config/wizard/v12.ts index 905a357f26..d70e5e8097 100644 --- a/src/shared/types/config/wizard/v12.ts +++ b/src/shared/types/config/wizard/v12.ts @@ -1,4 +1,4 @@ -import type {MarkupType, WidgetSizeType} from '../../..'; +import type {GradientNullMode, MarkupType, WidgetSizeType} from '../../..'; import type {ColorMode} from '../../../constants'; import type {DatasetFieldCalcMode, ParameterDefaultValue} from '../../dataset'; import type { @@ -294,6 +294,7 @@ export type V12ColorsConfig = { coloredByMeasure?: boolean; palette?: string; colorMode?: ColorMode; + nullMode?: GradientNullMode; }; export type V12ShapesConfig = { diff --git a/src/shared/types/wizard/index.ts b/src/shared/types/wizard/index.ts index 17be61dc03..11a9cfc930 100644 --- a/src/shared/types/wizard/index.ts +++ b/src/shared/types/wizard/index.ts @@ -13,6 +13,7 @@ import type { } from '../'; import type { ColorMode, + GradientNullMode, GradientType, NavigatorLinesMode, NavigatorPeriod, @@ -75,6 +76,7 @@ export interface ColorsConfig { coloredByMeasure?: boolean; palette?: string; colorMode?: ColorMode; + nullMode?: GradientNullMode; } export enum LabelsPositions { diff --git a/src/ui/units/wizard/actions/dialogColor.ts b/src/ui/units/wizard/actions/dialogColor.ts index 290ef56f0f..1f40c9d5f1 100644 --- a/src/ui/units/wizard/actions/dialogColor.ts +++ b/src/ui/units/wizard/actions/dialogColor.ts @@ -1,6 +1,6 @@ import {selectAvailableClientGradients} from 'constants/common'; -import type {ColorsConfig, Field, GradientType, PartialBy} from 'shared'; +import type {ColorsConfig, Field, GradientNullMode, GradientType, PartialBy} from 'shared'; import {closeDialog, openDialog} from 'store/actions/dialog'; import type {DatalensGlobalState} from 'ui'; @@ -42,6 +42,7 @@ export interface GradientState { rightThreshold?: string; gradientPalette: string; validationStatus?: ValidationStatus; + nullMode?: GradientNullMode; } export const RESET_DIALOG_COLOR_STATE = Symbol('wizard/dialogColor/RESET_DIALOG_COLOR_STATE'); @@ -141,6 +142,7 @@ export function prepareDialogColorState(props: { middleThreshold: colorsConfig?.middleThreshold || defaultGradientState.middleThreshold, rightThreshold: colorsConfig?.rightThreshold || defaultGradientState.rightThreshold, gradientPalette: colorsConfig?.gradientPalette || defaultGradientState.gradientPalette, + nullMode: colorsConfig?.nullMode || defaultGradientState.nullMode, }; const gradients = selectAvailableClientGradients(getState(), gradientState.gradientMode); diff --git a/src/ui/units/wizard/components/Dialogs/DialogColor/ColorSettingsContainer/ColorSettingsContainer.tsx b/src/ui/units/wizard/components/Dialogs/DialogColor/ColorSettingsContainer/ColorSettingsContainer.tsx index a468781bca..50362e39f5 100644 --- a/src/ui/units/wizard/components/Dialogs/DialogColor/ColorSettingsContainer/ColorSettingsContainer.tsx +++ b/src/ui/units/wizard/components/Dialogs/DialogColor/ColorSettingsContainer/ColorSettingsContainer.tsx @@ -48,6 +48,7 @@ type OwnProps = { onColorModeChange: (value: ColorMode) => void; isColorModeChangeAvailable: boolean; colorSectionFields?: Field[]; + visualizationId?: string; }; type StateProps = ReturnType; diff --git a/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColor.scss b/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColor.scss index a255a9839a..33fde7af43 100644 --- a/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColor.scss +++ b/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColor.scss @@ -11,7 +11,7 @@ } &_gradient-mode { - height: 370px; + height: 380px; .color-settings-container { &__row { diff --git a/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColor.tsx b/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColor.tsx index f9a047ed7a..ad624985e9 100644 --- a/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColor.tsx +++ b/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColor.tsx @@ -20,6 +20,7 @@ import { isGradientDialog, selectDialogColorGradientState, selectDialogColorPaletteState, + selectDialogColorVisualizationId, } from '../../../selectors/dialogColor'; import ColorSettingsContainer from './ColorSettingsContainer/ColorSettingsContainer'; @@ -117,6 +118,7 @@ class DialogColorComponent extends React.Component { colorMode={this.state.colorMode} isColorModeChangeAvailable={isColorModeChangeAvailable} onColorModeChange={this.onColorModeChange} + visualizationId={this.props.visualizationId} /> { leftThreshold, middleThreshold, rightThreshold, + nullMode, } = this.props.gradientState; config = { @@ -191,10 +194,11 @@ class DialogColorComponent extends React.Component { polygonBorders, reversed, thresholdsMode, - leftThreshold, - middleThreshold, - rightThreshold, + leftThreshold: leftThreshold ? leftThreshold : undefined, + middleThreshold: middleThreshold ? middleThreshold : undefined, + rightThreshold: rightThreshold ? rightThreshold : undefined, colorMode, + nullMode, }; return config; @@ -228,6 +232,7 @@ const mapStateToProps = (state: DatalensGlobalState) => { dataset: selectDataset(state), gradientState: selectDialogColorGradientState(state), paletteState: selectDialogColorPaletteState(state), + visualizationId: selectDialogColorVisualizationId(state), }; }; diff --git a/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColorGradient/DialogColorGradient.scss b/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColorGradient/DialogColorGradient.scss index 39bc2eb049..89ae7fff9e 100644 --- a/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColorGradient/DialogColorGradient.scss +++ b/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColorGradient/DialogColorGradient.scss @@ -2,44 +2,32 @@ .dialog-color-gradient { &__row { + --gc-form-row-label-width: 220px; margin-bottom: 20px; - vertical-align: middle; - line-height: 20px; - display: flex; - align-items: center; - } - - &__label { - display: inline-block; - margin-right: 20px; } &__palette-select { - width: 204px; + padding-inline-end: var(--g-spacing-2); + width: var(--gc-form-row-label-width); display: inline-block; } &__reverse-button { - margin-left: 6px; + margin-left: var(--g-spacing-2); line-height: 24px; vertical-align: middle; } - &__thresholds-checkbox { - margin-right: 10px; - } - &__threshold-inputs-wrapper { display: flex; width: 395px; - padding-right: 36px; - height: 28px; + padding-right: 44px; justify-content: space-between; } &__threshold-input { display: inline-block; - width: 80px; + width: 100px; } &__error-label { @@ -51,7 +39,6 @@ height: 28px; background: #000000; vertical-align: middle; - margin-left: 12px; } &__select { @@ -63,6 +50,6 @@ } &__hint-icon { - margin-left: 5px; + margin-left: var(--g-spacing-1); } } diff --git a/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColorGradient/DialogColorGradient.tsx b/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColorGradient/DialogColorGradient.tsx index 481fea1f4d..af6c40acb2 100644 --- a/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColorGradient/DialogColorGradient.tsx +++ b/src/ui/units/wizard/components/Dialogs/DialogColor/DialogColorGradient/DialogColorGradient.tsx @@ -1,10 +1,9 @@ import React from 'react'; -import {HelpPopover} from '@gravity-ui/components'; +import {FormRow, HelpPopover} from '@gravity-ui/components'; import {ArrowRightArrowLeft} from '@gravity-ui/icons'; -import {Button, Checkbox, Icon, RadioButton, Select, TextInput} from '@gravity-ui/uikit'; +import {Button, Checkbox, Flex, Icon, RadioButton, Select, TextInput} from '@gravity-ui/uikit'; import block from 'bem-cn-lite'; -import {FieldWrapper} from 'components/FieldWrapper/FieldWrapper'; import {i18n} from 'i18n'; import type {DatalensGlobalState} from 'index'; import {connect} from 'react-redux'; @@ -13,6 +12,10 @@ import {bindActionCreators} from 'redux'; import type {Field, GradientPalettes} from 'shared'; import {DialogColorQa, GradientType, isMeasureValue} from 'shared'; import {selectAvailableClientGradients, selectDefaultClientGradient} from 'ui'; +import { + ALLOWED_FOR_NULL_MODE_VISUALIZATIONS, + DEFAULT_NULL_MODE, +} from 'ui/units/wizard/constants/dialogColor'; import type {GradientState} from 'units/wizard/actions/dialogColor'; import {setDialogColorGradientState} from 'units/wizard/actions/dialogColor'; import {GradientPalettePreview} from 'units/wizard/components/GradientPalettePreview/GradientPalettePreview'; @@ -30,6 +33,11 @@ export const AUTO = 'auto'; const MANUAL = 'manual'; const TOOLTIP_DELAY_CLOSING = 250; +const NULLS_OPTIONS = [ + {value: 'ignore', content: i18n('wizard', 'label_painting-ignore')}, + {value: 'as-0', content: i18n('wizard', 'label_painting-as-0')}, +]; + type StateProps = ReturnType; type DispatchProps = ReturnType; @@ -40,6 +48,7 @@ interface Props extends StateProps, DispatchProps { }; setGradientState: (newGradientState: Partial) => void; item: Field; + visualizationId?: string; } class DialogColorGradientBody extends React.Component { @@ -75,11 +84,17 @@ class DialogColorGradientBody extends React.Component { rightThreshold, validationStatus, } = this.props.gradientState; - const {extra = {}, item, gradients} = this.props; + const {extra = {}, item, gradients, visualizationId} = this.props; + + const nullModeValue = this.props.gradientState.nullMode ?? DEFAULT_NULL_MODE; const currentPalette = this.getCurrentGradientPalette(gradients); const options = getGradientSelectorItems(gradients); + const canSetNullMode = ( + ALLOWED_FOR_NULL_MODE_VISUALIZATIONS as (string | undefined)[] + ).includes(visualizationId); + if (!currentPalette) { return null; } @@ -90,15 +105,17 @@ class DialogColorGradientBody extends React.Component { colors.reverse(); } + const leftThresholdError = validationStatus?.left?.text; + const middleThresholdError = validationStatus?.middle?.text; + const rightThresholdError = validationStatus?.right?.text; + return ( -
- {i18n('wizard', 'label_gradient-type')} + { - const gradientType = event.target.value as GradientType; + onUpdate={(gradientType) => { this.props.setGradientState({ gradientMode: gradientType, gradientPalette: selectDefaultClientGradient(gradientType), @@ -113,10 +130,9 @@ class DialogColorGradientBody extends React.Component { {i18n('wizard', 'label_3-point')} -
+ {extra.polygonBorders && ( -
- {i18n('wizard', 'label_borders')} + { {i18n('wizard', 'label_hide')} -
+ )} -
+