Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/i18n-keysets/wizard/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,12 @@
"label_default-period": "Default period",
"label_delete-all-filters-action": "Delete all filters in section",
"label_dialog-column-info-text": "The total width of the table always occupies 100% of the available space, regardless of the specified widths of the individual columns.",
"label_dialog-line-width": "Line width",
"label_dialog-radius": "Point size",
"label_dialog-radius-max": "Maximal point size",
"label_dialog-radius-min": "Minimal point size",
"label_dialog-shapes-chart-settings-tab": "General settings",
"label_dialog-shapes-line-settings-tab": "Lines",
"label_direction": "Direction",
"label_disabled": "Disabled",
"label_discrete": "Discrete",
Expand Down Expand Up @@ -188,6 +191,7 @@
"label_limit": "Limit",
"label_limit-input-error": "Enter a value from {{min}} to {{max}}",
"label_limit-message": "Only first 1000 values shown",
"label_line-width-auto-value": "Automatically",
"label_linear": "Linear",
"label_link-failed": "This dimension is not part of dataset links",
"label_links": "Links",
Expand Down
4 changes: 4 additions & 0 deletions src/i18n-keysets/wizard/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,12 @@
"label_default-period": "Период по умолчанию",
"label_delete-all-filters-action": "Удалить все фильтры в секции",
"label_dialog-column-info-text": "Общая ширина таблицы всегда занимает 100% доступного пространства вне зависимости от указанной ширины отдельных столбцов.",
"label_dialog-line-width": "Толщина линии",
"label_dialog-radius": "Размер точек",
"label_dialog-radius-max": "Максимальный размер точек",
"label_dialog-radius-min": "Минимальный размер точек",
"label_dialog-shapes-chart-settings-tab": "Общие настройки",
"label_dialog-shapes-line-settings-tab": "Линии",
"label_direction": "Направление",
"label_disabled": "Выключена",
"label_discrete": "Дискретный",
Expand Down Expand Up @@ -188,6 +191,7 @@
"label_limit": "Лимит",
"label_limit-input-error": "Введите значение от {{min}} до {{max}}",
"label_limit-message": "Выводится только первая тысяча значений",
"label_line-width-auto-value": "Автоматически",
"label_linear": "Линейная",
"label_link-failed": "Измерение не участвует в связи датасетов",
"label_links": "Связи",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ export function prepareGravityChartLine(args: PrepareFunctionArgs) {
shapeValue: graph.shapeValue,
},
rangeSlider,
lineWidth: graph.lineWidth,
};
});

Expand Down
20 changes: 20 additions & 0 deletions src/server/modes/charts/plugins/datalens/utils/shape-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,25 @@ export const mapAndShapeGraph = ({

graph.dashStyle = SHAPES_IN_ORDER[shapeIndex % SHAPES_IN_ORDER.length];
}

// Determine line width: use individual line width if set, otherwise fall back to chart-level width
let lineWidth: number | undefined;

if (title && shapesConfig?.mountedShapesLineWidths?.[title]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if title is an empty string (or null)? Is everything going to be okay?

// Individual line has a specific width set
lineWidth = shapesConfig.mountedShapesLineWidths[title];
} else if (shapesConfig?.lineWidth !== undefined) {
// Fall back to chart-level line width
lineWidth = shapesConfig.lineWidth;
}

if (lineWidth !== undefined) {
graph.lineWidth = lineWidth;
graph.states = {
hover: {
lineWidth: lineWidth + 2,
},
};
}
});
};
9 changes: 9 additions & 0 deletions src/shared/constants/qa/wizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,12 @@ export const enum ChartSettingsDialogQA {
IndicatorTitleMode = 'indicator-title-mode',
PreserveWhiteSpace = 'preserve-white-space',
}

export const enum DialogShapeSettings {
LineSettingsGraphScopeTabPanel = 'line-settings-graph-scope-tab-panel',
LineSettingsChartScopeTabPanel = 'line-settings-chart-scope-tab-panel',
LineSettingsGraphScopeTab = 'line-settings-graph-scope-tab',
LineSettingsChartScopeTab = 'line-settings-chart-scope-tab',
LineWidthSelectControl = 'line-width-select-control',
LineWidthSelectOption = 'line-width-select-option',
}
2 changes: 2 additions & 0 deletions src/shared/types/config/wizard/v15.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ export type V15ColorsConfig = {

export type V15ShapesConfig = {
mountedShapes?: Record<string, string>;
mountedShapesLineWidths?: Record<string, number>;
lineWidth?: number;
fieldGuid?: string;
};

Expand Down
2 changes: 2 additions & 0 deletions src/shared/types/wizard/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,8 @@ export type Sort = Field & {

export interface ShapesConfig {
mountedShapes?: Record<string, string>;
mountedShapesLineWidths?: Record<string, number>;
lineWidth?: number;
fieldGuid?: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
NumberFormatUnit,
} from 'shared';

import NumberInput from './NumberInput/NumberInput';
import NumberInput from '../NumberInput/NumberInput';

type Props = {
dataType: DATASET_FIELD_TYPES;
Expand Down
67 changes: 0 additions & 67 deletions src/ui/components/NumberFormatSettings/NumberInput/NumberInput.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
.wizard-number-input {
.number-input {
display: flex;
max-width: 120px;
max-width: 136px;
width: 136px;

&__input-button {
width: 45px;
}

// This beautiful crutch is already here
// https://github.com/gravity-ui/chartkit/blob/master/src/components/Widget/Table/Paginator/Paginator.scss#L25
Expand All @@ -14,5 +19,12 @@
& input[type='number'] {
-moz-appearance: textfield;
}
&__text-input {
width: 46px;
}
/* stylelint-enable */
&__text-input > .g-text-input__content {
border-left: none;
border-right: none;
}
}
121 changes: 121 additions & 0 deletions src/ui/components/NumberInput/NumberInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React from 'react';

import {TextInput} from '@gravity-ui/uikit';
import block from 'bem-cn-lite';

import {STEP_BUTTON_DIRECTION, StepButton} from './StepButton';

import './NumberInput.scss';

const b = block('number-input');

interface NumberInputProps {
value: number;
max?: number;
min?: number;
onChange: (value: number) => void;
qa?: string;
}

const NumberInput: React.FC<NumberInputProps> = ({
value,
onChange,
max = Infinity,
min = -Infinity,
qa,
}) => {
const [internalValue, setInternalValue] = React.useState<string>(String(value));

React.useEffect(() => {
setInternalValue(String(value));
}, [value]);

const commitValue = React.useCallback(
(newValue: number) => {
setInternalValue(String(newValue));
onChange(newValue);
},
[onChange],
);

const clampAndCommit = React.useCallback(
(delta = 0) => {
const parsed = parseInt(internalValue, 10);
const baseValue = Number.isNaN(parsed) ? value : parsed;
const newValue = baseValue + delta;

commitValue(Math.max(min, Math.min(max, newValue)));
},
[internalValue, min, max, commitValue, value],
);

const onBlur = React.useCallback(
(e: React.FocusEvent<HTMLInputElement>) => {
const relatedTarget = e.relatedTarget as HTMLElement | null;
if (relatedTarget?.closest(`.${b('input-button')}`)) {
return;
}

clampAndCommit();
},
[clampAndCommit],
);

const onKeyDown = React.useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
clampAndCommit();
}
},
[clampAndCommit],
);

const onInput = React.useCallback((newValue: string) => {
setInternalValue(newValue);
}, []);

const onPlus = React.useCallback(() => clampAndCommit(1), [clampAndCommit]);

const onMinus = React.useCallback(() => clampAndCommit(-1), [clampAndCommit]);

const memorizedInputAttrs: React.InputHTMLAttributes<HTMLInputElement> = React.useMemo(
() => ({
min: Number.isFinite(min) ? min : undefined,
max: Number.isFinite(max) ? max : undefined,
style: {textAlign: 'center'},
}),
[min, max],
);

const parsedInternal = parseInt(internalValue, 10);
const isMinusDisabled = !Number.isNaN(parsedInternal) && parsedInternal <= min;
const isPlusDisabled = !Number.isNaN(parsedInternal) && parsedInternal >= max;

return (
<div className={b({})}>
<StepButton
direction={STEP_BUTTON_DIRECTION.Minus}
disabled={isMinusDisabled}
onClick={onMinus}
/>
<TextInput
qa={qa}
type="number"
pin="brick-brick"
controlProps={memorizedInputAttrs}
value={internalValue}
onBlur={onBlur}
onUpdate={onInput}
onKeyDown={onKeyDown}
className={b('text-input')}
/>
<StepButton
direction={STEP_BUTTON_DIRECTION.Plus}
disabled={isPlusDisabled}
onClick={onPlus}
/>
</div>
);
};

export default NumberInput;
43 changes: 43 additions & 0 deletions src/ui/components/NumberInput/StepButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';

import {Minus, Plus} from '@gravity-ui/icons';
import {Button, Icon} from '@gravity-ui/uikit';
import block from 'bem-cn-lite';
import type {ValueOf} from 'shared';

import './NumberInput.scss';

const b = block('number-input');

export const STEP_BUTTON_DIRECTION = {
Plus: '+',
Minus: '-',
} as const;

export type StepButtonDirection = ValueOf<typeof STEP_BUTTON_DIRECTION>;

interface StepButtonProps {
direction: StepButtonDirection;
disabled: boolean;
onClick: () => void;
}

const DIRECTION_CONFIG: Record<
StepButtonDirection,
{icon: typeof Plus | typeof Minus; pin: 'brick-round' | 'round-brick'}
> = {
[STEP_BUTTON_DIRECTION.Plus]: {icon: Plus, pin: 'brick-round'},
[STEP_BUTTON_DIRECTION.Minus]: {icon: Minus, pin: 'round-brick'},
};

export const StepButton: React.FC<StepButtonProps> = ({direction, disabled, onClick}) => {
const {icon, pin} = DIRECTION_CONFIG[direction];

return (
<div className={b('input-button')}>
<Button view="outlined" pin={pin} width="max" disabled={disabled} onClick={onClick}>
<Icon data={icon} />
</Button>
</div>
);
};
Loading
Loading