[DASHBOARDS] Add prefix and suffix setting to the aggregate chart (#16216)
https://github.com/user-attachments/assets/0103cebe-e426-42d0-a8e4-b82494ef8503
This commit is contained in:
@@ -151,6 +151,8 @@ export type AggregateChartConfiguration = {
|
||||
format?: Maybe<Scalars['String']>;
|
||||
graphType: GraphType;
|
||||
label?: Maybe<Scalars['String']>;
|
||||
prefix?: Maybe<Scalars['String']>;
|
||||
suffix?: Maybe<Scalars['String']>;
|
||||
timezone?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
||||
@@ -151,6 +151,8 @@ export type AggregateChartConfiguration = {
|
||||
format?: Maybe<Scalars['String']>;
|
||||
graphType: GraphType;
|
||||
label?: Maybe<Scalars['String']>;
|
||||
prefix?: Maybe<Scalars['String']>;
|
||||
suffix?: Maybe<Scalars['String']>;
|
||||
timezone?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import styled from '@emotion/styled';
|
||||
import { useState } from 'react';
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
type CommandMenuItemTextInputProps = {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
placeholder?: string;
|
||||
};
|
||||
|
||||
const StyledRightAlignedTextInput = styled(TextInput)`
|
||||
input {
|
||||
:focus {
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
}
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
text-align: right;
|
||||
}
|
||||
`;
|
||||
|
||||
export const CommandMenuItemTextInput = ({
|
||||
value,
|
||||
onChange,
|
||||
placeholder,
|
||||
}: CommandMenuItemTextInputProps) => {
|
||||
const [draftValue, setDraftValue] = useState(value);
|
||||
|
||||
const handleChange = (text: string) => {
|
||||
setDraftValue(text);
|
||||
};
|
||||
|
||||
const handleCommit = () => {
|
||||
onChange(draftValue);
|
||||
};
|
||||
|
||||
const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {
|
||||
event.target.select();
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
handleCommit();
|
||||
};
|
||||
|
||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (event.key === Key.Enter || event.key === Key.Escape) {
|
||||
event.stopPropagation();
|
||||
handleCommit();
|
||||
} else {
|
||||
event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledRightAlignedTextInput
|
||||
value={draftValue}
|
||||
sizeVariant="sm"
|
||||
onChange={handleChange}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
);
|
||||
};
|
||||
+8
-55
@@ -1,6 +1,5 @@
|
||||
import { CommandGroup } from '@/command-menu/components/CommandGroup';
|
||||
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
|
||||
import { COMMAND_MENU_LIST_SELECTABLE_LIST_ID } from '@/command-menu/constants/CommandMenuListSelectableListId';
|
||||
import { useUpdateCommandMenuPageInfo } from '@/command-menu/hooks/useUpdateCommandMenuPageInfo';
|
||||
import { ChartSettingItem } from '@/command-menu/pages/page-layout/components/chart-settings/ChartSettingItem';
|
||||
import { ChartLimitInfoBanner } from '@/command-menu/pages/page-layout/components/ChartLimitInfoBanner';
|
||||
@@ -8,20 +7,14 @@ import { ChartTypeSelectionSection } from '@/command-menu/pages/page-layout/comp
|
||||
import { CHART_SETTINGS_HEADINGS } from '@/command-menu/pages/page-layout/constants/ChartSettingsHeadings';
|
||||
import { GRAPH_TYPE_INFORMATION } from '@/command-menu/pages/page-layout/constants/GraphTypeInformation';
|
||||
import { useChartSettingsValues } from '@/command-menu/pages/page-layout/hooks/useChartSettingsValues';
|
||||
import { useNavigatePageLayoutCommandMenu } from '@/command-menu/pages/page-layout/hooks/useNavigatePageLayoutCommandMenu';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useUpdateChartSettingInput } from '@/command-menu/pages/page-layout/hooks/useUpdateChartSettingInput';
|
||||
import { useUpdateChartSettingToggle } from '@/command-menu/pages/page-layout/hooks/useUpdateChartSettingToggle';
|
||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||
import { useGetConfigToUpdateAfterGraphTypeChange } from '@/command-menu/pages/page-layout/hooks/useUpdateGraphTypeConfig';
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { shouldHideChartSetting } from '@/command-menu/pages/page-layout/utils/shouldHideChartSetting';
|
||||
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { hasWidgetTooManyGroupsComponentState } from '@/page-layout/widgets/graph/states/hasWidgetTooManyGroupsComponentState';
|
||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
|
||||
import styled from '@emotion/styled';
|
||||
import { t } from '@lingui/core/macro';
|
||||
@@ -38,14 +31,9 @@ const StyledCommandMenuContainer = styled.div`
|
||||
|
||||
export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
||||
const { updateCommandMenuPageInfo } = useUpdateCommandMenuPageInfo();
|
||||
const { navigatePageLayoutCommandMenu } = useNavigatePageLayoutCommandMenu();
|
||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
||||
const { updateCurrentWidgetConfig } =
|
||||
useUpdateCurrentWidgetConfig(pageLayoutId);
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
const { setSelectedItemId } = useSelectableList(
|
||||
COMMAND_MENU_LIST_SELECTABLE_LIST_ID,
|
||||
);
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
if (widget.configuration?.__typename === 'IframeConfiguration') {
|
||||
@@ -60,14 +48,6 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
||||
configuration,
|
||||
});
|
||||
|
||||
const { updateChartSettingToggle } = useUpdateChartSettingToggle({
|
||||
pageLayoutId,
|
||||
objectMetadataId: widget.objectMetadataId,
|
||||
configuration,
|
||||
});
|
||||
|
||||
const { updateChartSettingInput } = useUpdateChartSettingInput(pageLayoutId);
|
||||
|
||||
const { getConfigToUpdateAfterGraphTypeChange } =
|
||||
useGetConfigToUpdateAfterGraphTypeChange({
|
||||
pageLayoutId,
|
||||
@@ -178,41 +158,14 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
||||
primaryAxisDateGranularity={primaryAxisDateGranularity}
|
||||
/>
|
||||
)}
|
||||
{visibleItems.map((item) => {
|
||||
const handleItemToggleChange = () => {
|
||||
setSelectedItemId(item.id);
|
||||
updateChartSettingToggle(item.id);
|
||||
};
|
||||
|
||||
const handleItemInputChange = (value: number | null) => {
|
||||
updateChartSettingInput(item.id, value);
|
||||
};
|
||||
|
||||
const handleItemDropdownOpen = () => {
|
||||
openDropdown({
|
||||
dropdownComponentInstanceIdFromProps: item.id,
|
||||
});
|
||||
};
|
||||
|
||||
const handleFilterClick = () => {
|
||||
navigatePageLayoutCommandMenu({
|
||||
commandMenuPage: CommandMenuPages.PageLayoutGraphFilter,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ChartSettingItem
|
||||
key={item.id}
|
||||
item={item}
|
||||
configuration={configuration}
|
||||
getChartSettingsValues={getChartSettingsValues}
|
||||
onToggleChange={handleItemToggleChange}
|
||||
onInputChange={handleItemInputChange}
|
||||
onDropdownOpen={handleItemDropdownOpen}
|
||||
onFilterClick={handleFilterClick}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{visibleItems.map((item) => (
|
||||
<ChartSettingItem
|
||||
key={item.id}
|
||||
item={item}
|
||||
objectMetadataId={widget.objectMetadataId}
|
||||
configuration={configuration}
|
||||
/>
|
||||
))}
|
||||
</CommandGroup>
|
||||
);
|
||||
})}
|
||||
|
||||
+95
-19
@@ -1,38 +1,86 @@
|
||||
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
|
||||
import { CommandMenuItemDropdown } from '@/command-menu/components/CommandMenuItemDropdown';
|
||||
import { CommandMenuItemNumberInput } from '@/command-menu/components/CommandMenuItemNumberInput';
|
||||
import { CommandMenuItemTextInput } from '@/command-menu/components/CommandMenuItemTextInput';
|
||||
import { CommandMenuItemToggle } from '@/command-menu/components/CommandMenuItemToggle';
|
||||
import { COMMAND_MENU_LIST_SELECTABLE_LIST_ID } from '@/command-menu/constants/CommandMenuListSelectableListId';
|
||||
import { useChartSettingsValues } from '@/command-menu/pages/page-layout/hooks/useChartSettingsValues';
|
||||
import { useNavigatePageLayoutCommandMenu } from '@/command-menu/pages/page-layout/hooks/useNavigatePageLayoutCommandMenu';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useUpdateChartSettingInput } from '@/command-menu/pages/page-layout/hooks/useUpdateChartSettingInput';
|
||||
import { useUpdateChartSettingTextInput } from '@/command-menu/pages/page-layout/hooks/useUpdateChartSettingTextInput';
|
||||
import { useUpdateChartSettingToggle } from '@/command-menu/pages/page-layout/hooks/useUpdateChartSettingToggle';
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||
import { isMinMaxRangeValid } from '@/command-menu/pages/page-layout/utils/isMinMaxRangeValid';
|
||||
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isString } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type ChartSettingItemProps = {
|
||||
item: ChartSettingsItem;
|
||||
objectMetadataId: string;
|
||||
configuration: ChartConfiguration;
|
||||
getChartSettingsValues: (
|
||||
itemId: CHART_CONFIGURATION_SETTING_IDS,
|
||||
) => boolean | string | undefined;
|
||||
onToggleChange: () => void;
|
||||
onInputChange: (value: number | null) => void;
|
||||
onDropdownOpen: () => void;
|
||||
onFilterClick: () => void;
|
||||
};
|
||||
|
||||
export const ChartSettingItem = ({
|
||||
item,
|
||||
objectMetadataId,
|
||||
configuration,
|
||||
getChartSettingsValues,
|
||||
onToggleChange,
|
||||
onInputChange,
|
||||
onDropdownOpen,
|
||||
onFilterClick,
|
||||
}: ChartSettingItemProps) => {
|
||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
const { setSelectedItemId } = useSelectableList(
|
||||
COMMAND_MENU_LIST_SELECTABLE_LIST_ID,
|
||||
);
|
||||
const { navigatePageLayoutCommandMenu } = useNavigatePageLayoutCommandMenu();
|
||||
|
||||
const { getChartSettingsValues } = useChartSettingsValues({
|
||||
objectMetadataId,
|
||||
configuration,
|
||||
});
|
||||
|
||||
const { updateChartSettingToggle } = useUpdateChartSettingToggle({
|
||||
pageLayoutId,
|
||||
objectMetadataId,
|
||||
configuration,
|
||||
});
|
||||
|
||||
const { updateChartSettingInput } = useUpdateChartSettingInput(pageLayoutId);
|
||||
|
||||
const { updateChartSettingTextInput } =
|
||||
useUpdateChartSettingTextInput(pageLayoutId);
|
||||
|
||||
const handleToggleChange = () => {
|
||||
setSelectedItemId(item.id);
|
||||
updateChartSettingToggle(item.id);
|
||||
};
|
||||
|
||||
const handleInputChange = (value: number | null) => {
|
||||
updateChartSettingInput(item.id, value);
|
||||
};
|
||||
|
||||
const handleTextInputChange = (value: string) => {
|
||||
updateChartSettingTextInput(item.id, value);
|
||||
};
|
||||
|
||||
const handleDropdownOpen = () => {
|
||||
openDropdown({
|
||||
dropdownComponentInstanceIdFromProps: item.id,
|
||||
});
|
||||
};
|
||||
|
||||
const handleFilterClick = () => {
|
||||
navigatePageLayoutCommandMenu({
|
||||
commandMenuPage: CommandMenuPages.PageLayoutGraphFilter,
|
||||
});
|
||||
};
|
||||
if (item.id === CHART_CONFIGURATION_SETTING_IDS.FILTER) {
|
||||
const filterValue = getChartSettingsValues(item.id);
|
||||
const filterDescription = isString(filterValue) ? filterValue : undefined;
|
||||
@@ -41,14 +89,14 @@ export const ChartSettingItem = ({
|
||||
<SelectableListItem
|
||||
key={item.id}
|
||||
itemId={item.id}
|
||||
onEnter={onFilterClick}
|
||||
onEnter={handleFilterClick}
|
||||
>
|
||||
<CommandMenuItem
|
||||
id={item.id}
|
||||
label={t(item.label)}
|
||||
Icon={item.Icon}
|
||||
hasSubMenu
|
||||
onClick={onFilterClick}
|
||||
onClick={handleFilterClick}
|
||||
description={filterDescription}
|
||||
contextualTextPosition="right"
|
||||
/>
|
||||
@@ -56,7 +104,7 @@ export const ChartSettingItem = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (isDefined(item.isInput)) {
|
||||
if (isDefined(item.isNumberInput)) {
|
||||
const settingValue = getChartSettingsValues(item.id);
|
||||
const stringValue = isString(settingValue) ? settingValue : '';
|
||||
|
||||
@@ -69,7 +117,7 @@ export const ChartSettingItem = ({
|
||||
RightComponent={
|
||||
<CommandMenuItemNumberInput
|
||||
value={stringValue}
|
||||
onChange={onInputChange}
|
||||
onChange={handleInputChange}
|
||||
onValidate={(value) =>
|
||||
!isDefined(value) ||
|
||||
isMinMaxRangeValid(
|
||||
@@ -90,26 +138,54 @@ export const ChartSettingItem = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (isDefined(item.isTextInput)) {
|
||||
const settingValue = getChartSettingsValues(item.id);
|
||||
const stringValue = isString(settingValue) ? settingValue : '';
|
||||
|
||||
return (
|
||||
<SelectableListItem key={item.id} itemId={item.id}>
|
||||
<CommandMenuItem
|
||||
id={item.id}
|
||||
label={t(item.label)}
|
||||
Icon={item.Icon}
|
||||
RightComponent={
|
||||
<CommandMenuItemTextInput
|
||||
value={stringValue}
|
||||
onChange={handleTextInputChange}
|
||||
placeholder={
|
||||
item.inputPlaceholder ? t(item.inputPlaceholder) : undefined
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
);
|
||||
}
|
||||
|
||||
if (item.isBoolean) {
|
||||
return (
|
||||
<SelectableListItem
|
||||
key={item.id}
|
||||
itemId={item.id}
|
||||
onEnter={onToggleChange}
|
||||
onEnter={handleToggleChange}
|
||||
>
|
||||
<CommandMenuItemToggle
|
||||
LeftIcon={item.Icon}
|
||||
text={t(item.label)}
|
||||
id={item.id}
|
||||
toggled={getChartSettingsValues(item.id) as boolean}
|
||||
onToggleChange={onToggleChange}
|
||||
onToggleChange={handleToggleChange}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SelectableListItem key={item.id} itemId={item.id} onEnter={onDropdownOpen}>
|
||||
<SelectableListItem
|
||||
key={item.id}
|
||||
itemId={item.id}
|
||||
onEnter={handleDropdownOpen}
|
||||
>
|
||||
<CommandMenuItemDropdown
|
||||
Icon={item.Icon}
|
||||
label={t(item.label)}
|
||||
|
||||
+6
@@ -2,6 +2,8 @@ import { CHART_SETTINGS_HEADINGS } from '@/command-menu/pages/page-layout/consta
|
||||
import { CHART_DATA_SOURCE_SETTING } from '@/command-menu/pages/page-layout/constants/settings/ChartDataSourceSetting';
|
||||
import { DATA_DISPLAY_AGGREGATE_SETTING } from '@/command-menu/pages/page-layout/constants/settings/DataDisplayAggregateSetting';
|
||||
import { FILTER_SETTING } from '@/command-menu/pages/page-layout/constants/settings/FilterSetting';
|
||||
import { PREFIX_SETTING } from '@/command-menu/pages/page-layout/constants/settings/PrefixSetting';
|
||||
import { SUFFIX_SETTING } from '@/command-menu/pages/page-layout/constants/settings/SuffixSetting';
|
||||
import { type ChartSettingsGroup } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||
|
||||
export const AGGREGATE_CHART_SETTINGS: ChartSettingsGroup[] = [
|
||||
@@ -13,4 +15,8 @@ export const AGGREGATE_CHART_SETTINGS: ChartSettingsGroup[] = [
|
||||
DATA_DISPLAY_AGGREGATE_SETTING,
|
||||
],
|
||||
},
|
||||
{
|
||||
heading: CHART_SETTINGS_HEADINGS.STYLE,
|
||||
items: [PREFIX_SETTING, SUFFIX_SETTING],
|
||||
},
|
||||
];
|
||||
|
||||
+2
@@ -24,4 +24,6 @@ export const CHART_CONFIGURATION_SETTING_LABELS = {
|
||||
DATE_GRANULARITY_Y: msg`Date granularity`,
|
||||
DATE_GRANULARITY: msg`Date granularity`,
|
||||
SHOW_LEGEND: msg`Legend`,
|
||||
PREFIX: msg`Prefix`,
|
||||
SUFFIX: msg`Suffix`,
|
||||
};
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { IconCaretLeft } from 'twenty-ui/display';
|
||||
|
||||
export const PREFIX_SETTING: ChartSettingsItem = {
|
||||
isBoolean: false,
|
||||
Icon: IconCaretLeft,
|
||||
label: CHART_CONFIGURATION_SETTING_LABELS.PREFIX,
|
||||
id: CHART_CONFIGURATION_SETTING_IDS.PREFIX,
|
||||
isTextInput: true,
|
||||
inputPlaceholder: msg`unit`,
|
||||
};
|
||||
+1
-1
@@ -9,6 +9,6 @@ export const RANGE_MAX_SETTING: ChartSettingsItem = {
|
||||
Icon: IconMathMax,
|
||||
label: CHART_CONFIGURATION_SETTING_LABELS.MAX_RANGE,
|
||||
id: CHART_CONFIGURATION_SETTING_IDS.MAX_RANGE,
|
||||
isInput: true,
|
||||
isNumberInput: true,
|
||||
inputPlaceholder: msg`Max`,
|
||||
};
|
||||
|
||||
+1
-1
@@ -9,6 +9,6 @@ export const RANGE_MIN_SETTING: ChartSettingsItem = {
|
||||
Icon: IconMathMin,
|
||||
label: CHART_CONFIGURATION_SETTING_LABELS.MIN_RANGE,
|
||||
id: CHART_CONFIGURATION_SETTING_IDS.MIN_RANGE,
|
||||
isInput: true,
|
||||
isNumberInput: true,
|
||||
inputPlaceholder: msg`Min`,
|
||||
};
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { IconCaretRight } from 'twenty-ui/display';
|
||||
|
||||
export const SUFFIX_SETTING: ChartSettingsItem = {
|
||||
isBoolean: false,
|
||||
Icon: IconCaretRight,
|
||||
label: CHART_CONFIGURATION_SETTING_LABELS.SUFFIX,
|
||||
id: CHART_CONFIGURATION_SETTING_IDS.SUFFIX,
|
||||
isTextInput: true,
|
||||
inputPlaceholder: msg`unit`,
|
||||
};
|
||||
+8
@@ -256,6 +256,14 @@ export const useChartSettingsValues = ({
|
||||
return isBarOrLineChart || isPieChart
|
||||
? (configuration.displayLegend ?? true)
|
||||
: true;
|
||||
case CHART_CONFIGURATION_SETTING_IDS.PREFIX:
|
||||
return configuration.__typename === 'AggregateChartConfiguration'
|
||||
? (configuration.prefix ?? '')
|
||||
: '';
|
||||
case CHART_CONFIGURATION_SETTING_IDS.SUFFIX:
|
||||
return configuration.__typename === 'AggregateChartConfiguration'
|
||||
? (configuration.suffix ?? '')
|
||||
: '';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { type CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { getConfigKeyFromSettingId } from '@/command-menu/pages/page-layout/utils/getConfigKeyFromSettingId';
|
||||
import { useUpdateCurrentWidgetConfig } from './useUpdateCurrentWidgetConfig';
|
||||
|
||||
export const useUpdateChartSettingTextInput = (pageLayoutId: string) => {
|
||||
const { updateCurrentWidgetConfig } =
|
||||
useUpdateCurrentWidgetConfig(pageLayoutId);
|
||||
|
||||
const updateChartSettingTextInput = (
|
||||
settingId: CHART_CONFIGURATION_SETTING_IDS,
|
||||
value: string,
|
||||
) => {
|
||||
const configKey = getConfigKeyFromSettingId(settingId);
|
||||
|
||||
updateCurrentWidgetConfig({
|
||||
configToUpdate: {
|
||||
[configKey]: value,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return { updateChartSettingTextInput };
|
||||
};
|
||||
+4
@@ -23,6 +23,8 @@ export enum CHART_CONFIGURATION_SETTING_IDS {
|
||||
DATE_GRANULARITY_Y = 'DATE_GRANULARITY_Y',
|
||||
DATE_GRANULARITY = 'DATE_GRANULARITY',
|
||||
SHOW_LEGEND = 'SHOW_LEGEND',
|
||||
PREFIX = 'PREFIX',
|
||||
SUFFIX = 'SUFFIX',
|
||||
}
|
||||
|
||||
export const CHART_CONFIGURATION_SETTING_TO_CONFIG_KEY_MAP = {
|
||||
@@ -39,4 +41,6 @@ export const CHART_CONFIGURATION_SETTING_TO_CONFIG_KEY_MAP = {
|
||||
'secondaryAxisGroupByDateGranularity',
|
||||
[CHART_CONFIGURATION_SETTING_IDS.DATE_GRANULARITY]: 'dateGranularity',
|
||||
[CHART_CONFIGURATION_SETTING_IDS.SHOW_LEGEND]: 'displayLegend',
|
||||
[CHART_CONFIGURATION_SETTING_IDS.PREFIX]: 'prefix',
|
||||
[CHART_CONFIGURATION_SETTING_IDS.SUFFIX]: 'suffix',
|
||||
} as const;
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@ export type ChartSettingsItem = {
|
||||
dependsOn?: CHART_CONFIGURATION_SETTING_IDS[];
|
||||
DropdownContent?: ComponentType;
|
||||
dropdownWidth?: number;
|
||||
isInput?: boolean;
|
||||
isNumberInput?: boolean;
|
||||
isTextInput?: boolean;
|
||||
inputPlaceholder?: MessageDescriptor;
|
||||
};
|
||||
|
||||
+9
-9
@@ -13,7 +13,7 @@ describe('shouldHideChartSetting', () => {
|
||||
label: msg`Data Labels`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: true,
|
||||
isInput: false,
|
||||
isNumberInput: false,
|
||||
};
|
||||
|
||||
const mockItemDependingOnSource: ChartSettingsItem = {
|
||||
@@ -21,7 +21,7 @@ describe('shouldHideChartSetting', () => {
|
||||
label: msg`X Axis Data`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: false,
|
||||
isInput: false,
|
||||
isNumberInput: false,
|
||||
dependsOn: [CHART_CONFIGURATION_SETTING_IDS.SOURCE],
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ describe('shouldHideChartSetting', () => {
|
||||
label: msg`Sort By Group`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: false,
|
||||
isInput: false,
|
||||
isNumberInput: false,
|
||||
dependsOn: [CHART_CONFIGURATION_SETTING_IDS.GROUP_BY],
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ describe('shouldHideChartSetting', () => {
|
||||
label: msg`X Axis Data`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: false,
|
||||
isInput: false,
|
||||
isNumberInput: false,
|
||||
dependsOn: [
|
||||
CHART_CONFIGURATION_SETTING_IDS.SOURCE,
|
||||
CHART_CONFIGURATION_SETTING_IDS.GROUP_BY,
|
||||
@@ -151,7 +151,7 @@ describe('shouldHideChartSetting', () => {
|
||||
label: msg`Data Labels`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: true,
|
||||
isInput: false,
|
||||
isNumberInput: false,
|
||||
dependsOn: undefined,
|
||||
};
|
||||
|
||||
@@ -170,7 +170,7 @@ describe('shouldHideChartSetting', () => {
|
||||
label: msg`Data Labels`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: true,
|
||||
isInput: false,
|
||||
isNumberInput: false,
|
||||
dependsOn: [],
|
||||
};
|
||||
|
||||
@@ -186,7 +186,7 @@ describe('shouldHideChartSetting', () => {
|
||||
label: msg`Date Granularity X`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: false,
|
||||
isInput: false,
|
||||
isNumberInput: false,
|
||||
};
|
||||
|
||||
const mockDateGranularityYItem: ChartSettingsItem = {
|
||||
@@ -194,7 +194,7 @@ describe('shouldHideChartSetting', () => {
|
||||
label: msg`Date Granularity Y`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: false,
|
||||
isInput: false,
|
||||
isNumberInput: false,
|
||||
};
|
||||
|
||||
const mockDateGranularityItem: ChartSettingsItem = {
|
||||
@@ -202,7 +202,7 @@ describe('shouldHideChartSetting', () => {
|
||||
label: msg`Date Granularity`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: false,
|
||||
isInput: false,
|
||||
isNumberInput: false,
|
||||
};
|
||||
|
||||
const mockObjectMetadataItem: ObjectMetadataItem = {
|
||||
|
||||
+10
-1
@@ -12,6 +12,8 @@ import {
|
||||
type GraphWidgetAggregateChartProps = {
|
||||
value: string | number;
|
||||
trendPercentage?: number;
|
||||
prefix?: string;
|
||||
suffix?: string;
|
||||
};
|
||||
|
||||
const StyledTrendPercentageValue = styled.span`
|
||||
@@ -43,6 +45,8 @@ const StyledH1Title = styled(H1Title)`
|
||||
export const GraphWidgetAggregateChart = ({
|
||||
value,
|
||||
trendPercentage,
|
||||
prefix,
|
||||
suffix,
|
||||
}: GraphWidgetAggregateChartProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
@@ -50,9 +54,14 @@ export const GraphWidgetAggregateChart = ({
|
||||
? formatNumberChartTrend(trendPercentage)
|
||||
: undefined;
|
||||
|
||||
const displayValue = `${prefix ?? ''}${value}${suffix ?? ''}`;
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledH1Title title={value} fontColor={H1TitleFontColor.Primary} />
|
||||
<StyledH1Title
|
||||
title={displayValue}
|
||||
fontColor={H1TitleFontColor.Primary}
|
||||
/>
|
||||
{isDefined(trendPercentage) && (
|
||||
<StyledTrendIconContainer>
|
||||
<StyledTrendPercentageValue>
|
||||
|
||||
+8
-2
@@ -19,9 +19,11 @@ export const GraphWidgetAggregateChartRenderer = ({
|
||||
}: {
|
||||
widget: PageLayoutWidget;
|
||||
}) => {
|
||||
const configuration = widget.configuration as AggregateChartConfiguration;
|
||||
|
||||
const { value, loading } = useGraphWidgetAggregateQuery({
|
||||
objectMetadataItemId: widget.objectMetadataId,
|
||||
configuration: widget.configuration as AggregateChartConfiguration,
|
||||
configuration,
|
||||
});
|
||||
|
||||
if (loading) {
|
||||
@@ -30,7 +32,11 @@ export const GraphWidgetAggregateChartRenderer = ({
|
||||
|
||||
return (
|
||||
<Suspense fallback={<ChartSkeletonLoader />}>
|
||||
<GraphWidgetAggregateChart value={value ?? '-'} />
|
||||
<GraphWidgetAggregateChart
|
||||
value={value ?? '-'}
|
||||
prefix={configuration.prefix ?? undefined}
|
||||
suffix={configuration.suffix ?? undefined}
|
||||
/>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
+10
@@ -73,4 +73,14 @@ export class AggregateChartConfigurationDTO {
|
||||
@Min(0)
|
||||
@Max(7)
|
||||
firstDayOfTheWeek?: number;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
prefix?: string;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
suffix?: string;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ export {
|
||||
IconCalendarTime,
|
||||
IconCalendarWeek,
|
||||
IconCalendarX,
|
||||
IconCaretLeft,
|
||||
IconCaretRight,
|
||||
IconChartBar,
|
||||
IconChartCandle,
|
||||
IconChartDots3,
|
||||
|
||||
@@ -120,6 +120,8 @@ export {
|
||||
IconCalendarTime,
|
||||
IconCalendarWeek,
|
||||
IconCalendarX,
|
||||
IconCaretLeft,
|
||||
IconCaretRight,
|
||||
IconChartBar,
|
||||
IconChartCandle,
|
||||
IconChartDots3,
|
||||
|
||||
Reference in New Issue
Block a user