✨ polishing report responsitivity (#3636)
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
@@ -0,0 +1,33 @@
|
||||
import React, { type ReactNode } from 'react';
|
||||
|
||||
import { type CSSProperties } from '../../style';
|
||||
|
||||
import { View } from './View';
|
||||
|
||||
type SpaceBetweenProps = {
|
||||
direction?: 'horizontal' | 'vertical';
|
||||
gap?: number;
|
||||
style?: CSSProperties;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export const SpaceBetween = ({
|
||||
direction = 'horizontal',
|
||||
gap = 15,
|
||||
style,
|
||||
children,
|
||||
}: SpaceBetweenProps) => {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flexWrap: 'wrap',
|
||||
flexDirection: direction === 'horizontal' ? 'row' : 'column',
|
||||
alignItems: 'center',
|
||||
gap,
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -52,7 +52,7 @@ export const Tooltip = ({
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{ minHeight: 'auto' }}
|
||||
style={{ minHeight: 'auto', flexShrink: 0 }}
|
||||
ref={triggerRef}
|
||||
onMouseEnter={handlePointerEnter}
|
||||
onMouseLeave={handlePointerLeave}
|
||||
|
||||
@@ -5,8 +5,12 @@ import { Button } from '../common/Button2';
|
||||
|
||||
export function CompactFiltersButton({ onPress }: { onPress: () => void }) {
|
||||
return (
|
||||
<Button variant="bare" onPress={onPress}>
|
||||
<SvgFilter width={15} height={15} />
|
||||
<Button variant="bare" onPress={onPress} style={{ minWidth: 20 }}>
|
||||
<SvgFilter
|
||||
width={15}
|
||||
height={15}
|
||||
style={{ width: 15, height: 15, flexShrink: 0 }}
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -62,8 +62,21 @@ export function FilterExpression<T extends RuleConditionEntity>({
|
||||
variant="bare"
|
||||
isDisabled={customName != null}
|
||||
onPress={() => setEditing(true)}
|
||||
style={{
|
||||
maxWidth: 'calc(100% - 26px)',
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'block',
|
||||
}}
|
||||
>
|
||||
<div style={{ paddingBlock: 1, paddingLeft: 5, paddingRight: 2 }}>
|
||||
<div
|
||||
style={{
|
||||
paddingBlock: 1,
|
||||
paddingLeft: 5,
|
||||
paddingRight: 2,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
}}
|
||||
>
|
||||
{customName ? (
|
||||
<Text style={{ color: theme.pageTextPositive }}>{customName}</Text>
|
||||
) : (
|
||||
|
||||
@@ -6,7 +6,10 @@ import { Button } from '../common/Button2';
|
||||
export function FiltersButton({ onPress }: { onPress: () => void }) {
|
||||
return (
|
||||
<Button variant="bare" onPress={onPress}>
|
||||
<SvgFilter style={{ width: 12, height: 12, marginRight: 5 }} /> Filter
|
||||
<SvgFilter
|
||||
style={{ width: 12, height: 12, marginRight: 5, flexShrink: 0 }}
|
||||
/>{' '}
|
||||
Filter
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useFeatureFlag } from '../../hooks/useFeatureFlag';
|
||||
import { useResponsive } from '../../ResponsiveProvider';
|
||||
import { Button } from '../common/Button2';
|
||||
import { Select } from '../common/Select';
|
||||
import { SpaceBetween } from '../common/SpaceBetween';
|
||||
import { View } from '../common/View';
|
||||
import { AppliedFilters } from '../filters/AppliedFilters';
|
||||
import { FilterButton } from '../filters/FiltersMenu';
|
||||
@@ -66,82 +67,69 @@ export function Header({
|
||||
<View
|
||||
style={{
|
||||
padding: 20,
|
||||
paddingTop: 0,
|
||||
paddingTop: 15,
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
<View
|
||||
<SpaceBetween
|
||||
direction={isNarrowWidth ? 'vertical' : 'horizontal'}
|
||||
style={{
|
||||
flexDirection: isNarrowWidth ? 'column' : 'row',
|
||||
alignItems: isNarrowWidth ? 'flex-start' : 'center',
|
||||
marginTop: 15,
|
||||
gap: 15,
|
||||
}}
|
||||
>
|
||||
{isDashboardsFeatureEnabled && mode && (
|
||||
<Button
|
||||
variant={mode === 'static' ? 'normal' : 'primary'}
|
||||
onPress={() => {
|
||||
const newMode = mode === 'static' ? 'sliding-window' : 'static';
|
||||
const [newStart, newEnd] = calculateTimeRange({
|
||||
start,
|
||||
end,
|
||||
mode: newMode,
|
||||
});
|
||||
|
||||
onChangeDates(newStart, newEnd, newMode);
|
||||
}}
|
||||
>
|
||||
{mode === 'static' ? 'Static' : 'Live'}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 5,
|
||||
}}
|
||||
>
|
||||
<Select
|
||||
onChange={newValue =>
|
||||
onChangeDates(
|
||||
...validateStart(
|
||||
allMonths[allMonths.length - 1].name,
|
||||
newValue,
|
||||
end,
|
||||
),
|
||||
)
|
||||
}
|
||||
value={start}
|
||||
defaultLabel={monthUtils.format(start, 'MMMM, yyyy')}
|
||||
options={allMonths.map(({ name, pretty }) => [name, pretty])}
|
||||
/>
|
||||
<View>to</View>
|
||||
<Select
|
||||
onChange={newValue =>
|
||||
onChangeDates(
|
||||
...validateEnd(
|
||||
allMonths[allMonths.length - 1].name,
|
||||
<SpaceBetween gap={isNarrowWidth ? 5 : undefined}>
|
||||
{isDashboardsFeatureEnabled && mode && (
|
||||
<Button
|
||||
variant={mode === 'static' ? 'normal' : 'primary'}
|
||||
onPress={() => {
|
||||
const newMode = mode === 'static' ? 'sliding-window' : 'static';
|
||||
const [newStart, newEnd] = calculateTimeRange({
|
||||
start,
|
||||
newValue,
|
||||
),
|
||||
)
|
||||
}
|
||||
value={end}
|
||||
options={allMonths.map(({ name, pretty }) => [name, pretty])}
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
</View>
|
||||
end,
|
||||
mode: newMode,
|
||||
});
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 15,
|
||||
flexWrap: 'wrap',
|
||||
}}
|
||||
>
|
||||
onChangeDates(newStart, newEnd, newMode);
|
||||
}}
|
||||
>
|
||||
{mode === 'static' ? 'Static' : 'Live'}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<SpaceBetween gap={5}>
|
||||
<Select
|
||||
onChange={newValue =>
|
||||
onChangeDates(
|
||||
...validateStart(
|
||||
allMonths[allMonths.length - 1].name,
|
||||
newValue,
|
||||
end,
|
||||
),
|
||||
)
|
||||
}
|
||||
value={start}
|
||||
defaultLabel={monthUtils.format(start, 'MMMM, yyyy')}
|
||||
options={allMonths.map(({ name, pretty }) => [name, pretty])}
|
||||
/>
|
||||
<View>to</View>
|
||||
<Select
|
||||
onChange={newValue =>
|
||||
onChangeDates(
|
||||
...validateEnd(
|
||||
allMonths[allMonths.length - 1].name,
|
||||
start,
|
||||
newValue,
|
||||
),
|
||||
)
|
||||
}
|
||||
value={end}
|
||||
options={allMonths.map(({ name, pretty }) => [name, pretty])}
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
</SpaceBetween>
|
||||
</SpaceBetween>
|
||||
|
||||
<SpaceBetween>
|
||||
{show1Month && (
|
||||
<Button
|
||||
variant="bare"
|
||||
@@ -187,7 +175,7 @@ export function Header({
|
||||
exclude={undefined}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</SpaceBetween>
|
||||
|
||||
{children ? (
|
||||
<View
|
||||
@@ -202,7 +190,7 @@ export function Header({
|
||||
) : (
|
||||
<View style={{ flex: 1 }} />
|
||||
)}
|
||||
</View>
|
||||
</SpaceBetween>
|
||||
|
||||
{filters && filters.length > 0 && (
|
||||
<View style={{ marginTop: 5 }}>
|
||||
|
||||
@@ -25,7 +25,6 @@ export function ModeButton({
|
||||
css({
|
||||
padding: '5px 10px',
|
||||
backgroundColor: theme.menuBackground,
|
||||
marginRight: 5,
|
||||
fontSize: 'inherit',
|
||||
...style,
|
||||
...(selected && {
|
||||
|
||||
@@ -14,6 +14,7 @@ import { Button } from '../common/Button2';
|
||||
import { Menu } from '../common/Menu';
|
||||
import { Popover } from '../common/Popover';
|
||||
import { Select, type SelectOption } from '../common/Select';
|
||||
import { SpaceBetween } from '../common/SpaceBetween';
|
||||
import { Text } from '../common/Text';
|
||||
import { Tooltip } from '../common/Tooltip';
|
||||
import { View } from '../common/View';
|
||||
@@ -177,16 +178,13 @@ export function ReportSidebar({
|
||||
<strong>Display</strong>
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
<SpaceBetween
|
||||
gap={5}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
padding: 5,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Text style={{ width: 50, textAlign: 'right', marginRight: 5 }}>
|
||||
Mode:
|
||||
</Text>
|
||||
<Text style={{ width: 50, textAlign: 'right' }}>Mode:</Text>
|
||||
<ModeButton
|
||||
selected={customReportItems.mode === 'total'}
|
||||
onSelect={() => onChangeMode('total')}
|
||||
@@ -199,7 +197,7 @@ export function ReportSidebar({
|
||||
>
|
||||
Time
|
||||
</ModeButton>
|
||||
</View>
|
||||
</SpaceBetween>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
@@ -394,12 +392,11 @@ export function ReportSidebar({
|
||||
flexShrink: 0,
|
||||
}}
|
||||
/>
|
||||
<View
|
||||
<SpaceBetween
|
||||
gap={5}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
marginTop: 10,
|
||||
marginBottom: 5,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Text>
|
||||
@@ -430,7 +427,7 @@ export function ReportSidebar({
|
||||
>
|
||||
Static
|
||||
</ModeButton>
|
||||
</View>
|
||||
</SpaceBetween>
|
||||
{!customReportItems.isDateStatic ? (
|
||||
<View
|
||||
style={{
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
} from '../../icons/v1';
|
||||
import { SvgChartArea } from '../../icons/v1/ChartArea';
|
||||
import { theme } from '../../style';
|
||||
import { SpaceBetween } from '../common/SpaceBetween';
|
||||
import { View } from '../common/View';
|
||||
import { FilterButton } from '../filters/FiltersMenu';
|
||||
|
||||
@@ -70,6 +71,7 @@ export function ReportTopbar({
|
||||
alignItems: 'center',
|
||||
marginBottom: 10,
|
||||
flexShrink: 0,
|
||||
overflowY: 'auto',
|
||||
}}
|
||||
>
|
||||
<GraphButton
|
||||
@@ -177,6 +179,7 @@ export function ReportTopbar({
|
||||
>
|
||||
<SvgTag width={15} height={15} />
|
||||
</GraphButton>
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: 1,
|
||||
@@ -185,27 +188,35 @@ export function ReportTopbar({
|
||||
marginRight: 15,
|
||||
flexShrink: 0,
|
||||
}}
|
||||
/>{' '}
|
||||
<FilterButton
|
||||
compact
|
||||
hover
|
||||
onApply={(e: RuleConditionEntity) => {
|
||||
setSessionReport('conditions', [
|
||||
...(customReportItems.conditions ?? []),
|
||||
e,
|
||||
]);
|
||||
onApplyFilter(e);
|
||||
onReportChange({ type: 'modify' });
|
||||
/>
|
||||
|
||||
<SpaceBetween
|
||||
style={{
|
||||
flexWrap: 'nowrap',
|
||||
justifyContent: 'space-between',
|
||||
flex: 1,
|
||||
}}
|
||||
exclude={[]}
|
||||
/>
|
||||
<View style={{ flex: 1 }} />
|
||||
<SaveReport
|
||||
customReportItems={customReportItems}
|
||||
report={report}
|
||||
savedStatus={savedStatus}
|
||||
onReportChange={onReportChange}
|
||||
/>
|
||||
>
|
||||
<FilterButton
|
||||
compact
|
||||
hover
|
||||
onApply={(e: RuleConditionEntity) => {
|
||||
setSessionReport('conditions', [
|
||||
...(customReportItems.conditions ?? []),
|
||||
e,
|
||||
]);
|
||||
onApplyFilter(e);
|
||||
onReportChange({ type: 'modify' });
|
||||
}}
|
||||
exclude={[]}
|
||||
/>
|
||||
<SaveReport
|
||||
customReportItems={customReportItems}
|
||||
report={report}
|
||||
savedStatus={savedStatus}
|
||||
onReportChange={onReportChange}
|
||||
/>
|
||||
</SpaceBetween>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -727,7 +727,6 @@ export function CustomReport() {
|
||||
marginLeft: 5,
|
||||
marginRight: 5,
|
||||
gap: 10,
|
||||
alignItems: 'flex-start',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -23,6 +23,7 @@ import { Block } from '../../common/Block';
|
||||
import { Button } from '../../common/Button2';
|
||||
import { Paragraph } from '../../common/Paragraph';
|
||||
import { Select } from '../../common/Select';
|
||||
import { SpaceBetween } from '../../common/SpaceBetween';
|
||||
import { Text } from '../../common/Text';
|
||||
import { Tooltip } from '../../common/Tooltip';
|
||||
import { View } from '../../common/View';
|
||||
@@ -235,13 +236,7 @@ function SpendingInternal({ widget }: SpendingInternalProps) {
|
||||
}}
|
||||
>
|
||||
{!isNarrowWidth && (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
<SpaceBetween gap={0}>
|
||||
{isDashboardsFeatureEnabled && (
|
||||
<>
|
||||
<Button
|
||||
@@ -263,14 +258,7 @@ function SpendingInternal({ widget }: SpendingInternalProps) {
|
||||
</>
|
||||
)}
|
||||
|
||||
<View
|
||||
style={{
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row',
|
||||
marginRight: 5,
|
||||
gap: 5,
|
||||
}}
|
||||
>
|
||||
<SpaceBetween gap={5}>
|
||||
<Text>
|
||||
<Trans>Compare</Trans>
|
||||
</Text>
|
||||
@@ -305,7 +293,7 @@ function SpendingInternal({ widget }: SpendingInternalProps) {
|
||||
style={{ width: 150 }}
|
||||
popoverStyle={{ width: 150 }}
|
||||
/>
|
||||
</View>
|
||||
</SpaceBetween>
|
||||
|
||||
<View
|
||||
style={{
|
||||
@@ -313,16 +301,11 @@ function SpendingInternal({ widget }: SpendingInternalProps) {
|
||||
height: 28,
|
||||
backgroundColor: theme.pillBorderDark,
|
||||
marginRight: 15,
|
||||
marginLeft: 10,
|
||||
marginLeft: 15,
|
||||
}}
|
||||
/>
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
marginRight: 5,
|
||||
}}
|
||||
>
|
||||
<SpaceBetween gap={5}>
|
||||
<ModeButton
|
||||
selected={reportMode === 'single-month'}
|
||||
style={{
|
||||
@@ -356,7 +339,7 @@ function SpendingInternal({ widget }: SpendingInternalProps) {
|
||||
>
|
||||
<Trans>Average</Trans>
|
||||
</ModeButton>
|
||||
</View>
|
||||
</SpaceBetween>
|
||||
|
||||
<View
|
||||
style={{
|
||||
@@ -409,7 +392,7 @@ function SpendingInternal({ widget }: SpendingInternalProps) {
|
||||
</Tooltip>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</SpaceBetween>
|
||||
)}
|
||||
|
||||
{conditions && conditions.length > 0 && (
|
||||
|
||||
6
upcoming-release-notes/3636.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Enhancements
|
||||
authors: [MatissJanis]
|
||||
---
|
||||
|
||||
Reports: responsibility UI polishing.
|
||||