Skip to content
Merged
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
14 changes: 14 additions & 0 deletions locales/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -10880,6 +10880,20 @@
"value": "No"
}
],
"noCurrentData": [
{
"type": 0,
"value": "No data available for "
},
{
"type": 1,
"value": "dateRange"
},
{
"type": 0,
"value": ". You are viewing data for the previous month."
}
],
"noDataForDate": [
{
"type": 0,
Expand Down
1 change: 1 addition & 0 deletions locales/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@
"networkUnattributedDistributedDesc": "Costs associated with ingress and egress network traffic for individual nodes.",
"next": "next",
"no": "No",
"noCurrentData": "No data available for {dateRange}. You are viewing data for the previous month.",
"noDataForDate": "No data available for {dateRange}",
"noDataStateDesc": "We have detected an integration, but we are not done processing the incoming data. {status}The time to process could take up to 24 hours. Try refreshing the page at a later time.",
"noDataStateRefresh": "Refresh this page",
Expand Down
8 changes: 8 additions & 0 deletions src/components/featureToggle/featureToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const enum FeatureToggle {
accountInfoEmptyState = 'cost-management.ui.account-info-empty-state', // https://issues.redhat.com/browse/COST-5335
awsEc2Instances = 'cost-management.ui.aws-ec2-instances', // https://issues.redhat.com/browse/COST-4855
debug = 'cost-management.ui.debug',
detailsDateRange = 'cost-management.ui.details-date-range', // https://issues.redhat.com/browse/COST-5563
exports = 'cost-management.ui.exports', // Async exports https://issues.redhat.com/browse/COST-2223
finsights = 'cost-management.ui.finsights', // RHEL support for FINsights https://issues.redhat.com/browse/COST-3306
ibm = 'cost-management.ui.ibm', // IBM https://issues.redhat.com/browse/COST-935
Expand All @@ -31,6 +32,10 @@ export const useIsDebugToggleEnabled = () => {
return useIsToggleEnabled(FeatureToggle.debug);
};

export const useIsDetailsDateRangeToggleEnabled = () => {
return useIsToggleEnabled(FeatureToggle.detailsDateRange);
};

export const useIsExportsToggleEnabled = () => {
return useIsToggleEnabled(FeatureToggle.exports);
};
Expand All @@ -55,6 +60,7 @@ export const useFeatureToggle = () => {
const isAccountInfoEmptyStateToggleEnabled = useIsAccountInfoEmptyStateToggleEnabled();
const isAwsEc2InstancesToggleEnabled = useIsAwsEc2InstancesToggleEnabled();
const isDebugToggleEnabled = useIsDebugToggleEnabled();
const isDetailsDateRangeToggleEnabled = useIsDetailsDateRangeToggleEnabled();
const isExportsToggleEnabled = useIsExportsToggleEnabled();
const isFinsightsToggleEnabled = useIsFinsightsToggleEnabled();
const isIbmToggleEnabled = useIsIbmToggleEnabled();
Expand All @@ -73,6 +79,7 @@ export const useFeatureToggle = () => {
isAccountInfoEmptyStateToggleEnabled,
isAwsEc2InstancesToggleEnabled,
isDebugToggleEnabled,
isDetailsDateRangeToggleEnabled,
isExportsToggleEnabled,
isFinsightsToggleEnabled,
isIbmToggleEnabled,
Expand All @@ -87,6 +94,7 @@ export const useFeatureToggle = () => {
isAccountInfoEmptyStateToggleEnabled,
isAwsEc2InstancesToggleEnabled,
isDebugToggleEnabled,
isDetailsDateRangeToggleEnabled,
isExportsToggleEnabled,
isFinsightsToggleEnabled,
isIbmToggleEnabled,
Expand Down
5 changes: 5 additions & 0 deletions src/locales/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2586,6 +2586,11 @@ export default defineMessages({
description: 'No',
id: 'no',
},
noCurrentData: {
defaultMessage: 'No data available for {dateRange}. You are viewing data for the previous month.',
description: 'No data available for Jan 1-31. You are viewing data for the previous month.',
id: 'noCurrentData',
},
noDataForDate: {
defaultMessage: 'No data available for {dateRange}',
description: 'No data available for Jan 1-31',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,12 @@ class HistoricalTrendChartBase extends React.Component<HistoricalTrendChartProps
series.map((s, index) => {
return this.getChart(s, index);
})}
<ChartAxis label={xAxisLabel} style={chartStyles.xAxis} tickValues={[1, midDate, endDate]} />
<ChartAxis
fixAxisLabelHeight
label={xAxisLabel}
style={chartStyles.xAxis}
tickValues={[1, midDate, endDate]}
/>
<ChartAxis dependentAxis label={yAxisLabel} style={chartStyles.yAxis} />
</Chart>
</div>
Expand Down
7 changes: 7 additions & 0 deletions src/routes/components/dateRange/dateRange.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@import url("~@patternfly/patternfly/base/patternfly-variables.css");

.dropdownOverride {
button.pf-v5-c-menu-toggle {
max-width: unset;
}
}
95 changes: 95 additions & 0 deletions src/routes/components/dateRange/dateRange.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import './dateRange.scss';

import type { MessageDescriptor } from '@formatjs/intl/src/types';
import type { MenuToggleElement } from '@patternfly/react-core';
import { Dropdown, DropdownItem, DropdownList, MenuToggle } from '@patternfly/react-core';
import messages from 'locales/messages';
import React from 'react';
import { useIntl } from 'react-intl';
import { getSinceDateRangeString } from 'utils/dates';

interface DateRangeOwnProps {
dateRangeType?: string;
isCurrentMonthData: boolean;
isDisabled?: boolean;
isExplorer?: boolean;
onSelect(value: string);
}

type DateRangeProps = DateRangeOwnProps;

const DateRange: React.FC<DateRangeProps> = ({ dateRangeType, isCurrentMonthData, isExplorer, onSelect }) => {
const [isOpen, setIsOpen] = React.useState(false);
const intl = useIntl();

const onToggleClick = () => {
setIsOpen(!isOpen);
};

const getOptions = () => {
const options: {
isDisabled?: boolean;
label: MessageDescriptor;
value: string;
}[] = [
{ label: messages.explorerDateRange, value: 'current_month_to_date', isDisabled: isCurrentMonthData === false },
{ label: messages.explorerDateRange, value: 'previous_month' },
];
if (isExplorer) {
options.push(
{ label: messages.explorerDateRange, value: 'previous_month_to_date' },
{ label: messages.explorerDateRange, value: 'last_thirty_days' },
{ label: messages.explorerDateRange, value: 'last_sixty_days' },
{ label: messages.explorerDateRange, value: 'last_ninety_days' },
{ label: messages.explorerDateRange, value: 'custom' }
);
}
return options;
};

const handleOnSelect = (_evt, value) => {
if (onSelect) {
onSelect(value);
}
setIsOpen(false);
};

return (
<div className="dropdownOverride">
<Dropdown
isOpen={isOpen}
onSelect={handleOnSelect}
onOpenChange={(val: boolean) => setIsOpen(val)}
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen} isFullWidth>
{intl.formatMessage(messages.explorerDateRange, { value: dateRangeType })}
</MenuToggle>
)}
>
<DropdownList>
{getOptions().map((option, index) => (
<DropdownItem
value={option.value}
isAriaDisabled={option.isDisabled}
key={index}
tooltipProps={
option.isDisabled
? {
content: intl.formatMessage(messages.noDataForDate, {
dateRange: getSinceDateRangeString(undefined, option.value === 'previous_month' ? 1 : 0, true),
}),
position: 'right',
}
: undefined
}
>
{intl.formatMessage(option.label, { value: option.value })}
</DropdownItem>
))}
</DropdownList>
</Dropdown>
</div>
);
};

export { DateRange };
1 change: 1 addition & 0 deletions src/routes/components/dateRange/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './dateRange';
21 changes: 13 additions & 8 deletions src/routes/components/export/exportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ export interface ExportModalOwnProps {
showAggregateType?: boolean; // Monthly resolution filters are not valid with date range
showFormatType?: boolean; // Format type; CVS / JSON
showTimeScope?: boolean; // timeScope filters are not valid with date range
timeScopeValue?: number;
}

interface ExportModalStateProps {
isDetailsDateRangeToggleEnabled?: boolean;
isExportsToggleEnabled?: boolean;
}

Expand Down Expand Up @@ -89,16 +91,17 @@ export class ExportModalBase extends React.Component<ExportModalProps, ExportMod
protected defaultState: ExportModalState = {
error: undefined,
formatType: 'csv',
timeScope: 'current',
resolution: this.props.resolution || 'monthly',
timeScope: this.props.timeScopeValue === -2 ? 'previous' : 'current',
};
public state: ExportModalState = { ...this.defaultState };

constructor(stateProps, dispatchProps) {
super(stateProps, dispatchProps);
this.handleOnMonthChange = this.handleOnMonthChange.bind(this);
this.handleOnResolutionChange = this.handleOnResolutionChange.bind(this);
this.handleOnTypeChange = this.handleOnTypeChange.bind(this);
public componentDidUpdate(prevProps: ExportModalProps) {
const { timeScopeValue } = this.props;

if (timeScopeValue !== prevProps.timeScopeValue) {
this.setState({ timeScope: timeScopeValue === -2 ? 'previous' : 'current' });
}
}

// Reset default state upon close -- see https://issues.redhat.com/browse/COST-1134
Expand Down Expand Up @@ -145,6 +148,7 @@ export class ExportModalBase extends React.Component<ExportModalProps, ExportMod
groupBy,
intl,
isAllItems,
isDetailsDateRangeToggleEnabled,
isExportsToggleEnabled,
isTimeScoped,
items,
Expand All @@ -153,7 +157,7 @@ export class ExportModalBase extends React.Component<ExportModalProps, ExportMod
reportType,
showAggregateType = true,
showFormatType = true,
showTimeScope = true,
showTimeScope = isDetailsDateRangeToggleEnabled ? false : true,
} = this.props;
const { error, formatType, name, resolution, timeScope } = this.state;

Expand Down Expand Up @@ -207,7 +211,7 @@ export class ExportModalBase extends React.Component<ExportModalProps, ExportMod
isTimeScoped={isTimeScoped}
items={items}
key="confirm"
timeScope={showTimeScope ? timeScope : undefined}
timeScope={timeScope}
onClose={this.handleOnClose}
onError={this.handleOnError}
name={defaultName}
Expand Down Expand Up @@ -334,6 +338,7 @@ export class ExportModalBase extends React.Component<ExportModalProps, ExportMod

const mapStateToProps = createMapStateToProps<ExportModalOwnProps, unknown>(state => {
return {
isDetailsDateRangeToggleEnabled: FeatureToggleSelectors.selectIsDetailsDateRangeToggleEnabled(state),
isExportsToggleEnabled: FeatureToggleSelectors.selectIsExportsToggleEnabled(state),
};
});
Expand Down
4 changes: 3 additions & 1 deletion src/routes/components/groupBy/groupBy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { SelectWrapperOption } from 'routes/components/selectWrapper';
import { SelectWrapper } from 'routes/components/selectWrapper';
import type { PerspectiveType } from 'routes/explorer/explorerUtils';
import { getDateRangeFromQuery } from 'routes/utils/dateRange';
import { getTimeScopeValue } from 'routes/utils/timeScope';
import type { FetchStatus } from 'store/common';
import { createMapStateToProps } from 'store/common';
import { orgActions, orgSelectors } from 'store/orgs';
Expand Down Expand Up @@ -326,13 +327,14 @@ class GroupByBase extends React.Component<GroupByProps, GroupByState> {
const mapStateToProps = createMapStateToProps<GroupByOwnProps, GroupByStateProps>(
(state, { orgPathsType, router, resourcePathsType, tagPathsType }) => {
const queryFromRoute = parseQuery<Query>(router.location.search);
const timeScopeValue = getTimeScopeValue(queryFromRoute);

// Default to current month filter for details pages
let tagFilter: any = {
filter: {
resolution: 'monthly',
time_scope_units: 'month',
time_scope_value: -1,
time_scope_value: timeScopeValue !== undefined ? timeScopeValue : -1,
},
};

Expand Down
7 changes: 5 additions & 2 deletions src/routes/details/awsBreakdown/awsBreakdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { BreakdownBase } from 'routes/details/components/breakdown';
import { getGroupById, getGroupByOrgValue, getGroupByValue } from 'routes/utils/groupBy';
import { filterProviders } from 'routes/utils/providers';
import { getQueryState } from 'routes/utils/queryState';
import { getTimeScopeValue } from 'routes/utils/timeScope';
import { createMapStateToProps } from 'store/common';
import { FeatureToggleSelectors } from 'store/featureToggle';
import { providersQuery, providersSelectors } from 'store/providers';
Expand Down Expand Up @@ -56,6 +57,7 @@ const mapStateToProps = createMapStateToProps<AwsBreakdownOwnProps, BreakdownSta

const costType = getCostType();
const currency = getCurrency();
const timeScopeValue = getTimeScopeValue(queryState);

const query = { ...queryFromRoute };
const reportQuery = {
Expand All @@ -64,7 +66,7 @@ const mapStateToProps = createMapStateToProps<AwsBreakdownOwnProps, BreakdownSta
filter: {
resolution: 'monthly',
time_scope_units: 'month',
time_scope_value: -1,
time_scope_value: timeScopeValue !== undefined ? timeScopeValue : -1,
},
filter_by: {
// Add filters here to apply logical OR/AND
Expand Down Expand Up @@ -120,7 +122,7 @@ const mapStateToProps = createMapStateToProps<AwsBreakdownOwnProps, BreakdownSta
emptyStateTitle: intl.formatMessage(messages.awsDetailsTitle),
groupBy,
groupByValue,
historicalDataComponent: <HistoricalData costType={costType} currency={currency} />,
historicalDataComponent: <HistoricalData costType={costType} currency={currency} timeScopeValue={timeScopeValue} />,
instancesComponent:
groupBy === serviceKey && groupByValue === 'AmazonEC2' ? (
<Instances costType={costType} currency={currency} />
Expand All @@ -139,6 +141,7 @@ const mapStateToProps = createMapStateToProps<AwsBreakdownOwnProps, BreakdownSta
reportQueryString,
showCostType: true,
tagPathsType: TagPathsType.aws,
timeScopeValue,
title,
};
});
Expand Down
2 changes: 1 addition & 1 deletion src/routes/details/awsBreakdown/historicalData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { awsHistoricalDataSelectors } from 'store/breakdown/historicalData/awsHi
import { createMapStateToProps } from 'store/common';

interface AwsHistoricalDataOwnProps {
// TBD...
timeScopeValue?: number;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down
4 changes: 3 additions & 1 deletion src/routes/details/awsBreakdown/instances/instances.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type { ComputedReportItem } from 'routes/utils/computedReport/getComputed
import { getUnsortedComputedReportItems } from 'routes/utils/computedReport/getComputedReportItems';
import { getExcludeTagKey, getFilterByTagKey } from 'routes/utils/groupBy';
import * as queryUtils from 'routes/utils/query';
import { getTimeScopeValue } from 'routes/utils/timeScope';
import type { RootState } from 'store';
import { FetchStatus } from 'store/common';
import { reportActions, reportSelectors } from 'store/reports';
Expand Down Expand Up @@ -333,6 +334,7 @@ const useMapToProps = ({ costType, currency, query }): InstancesStateProps => {
const dispatch: ThunkDispatch<RootState, any, AnyAction> = useDispatch();
const queryFromRoute = useQueryFromRoute();
const queryState = useQueryState('details');
const timeScopeValue = getTimeScopeValue(queryState);

const reportQuery = {
cost_type: costType,
Expand All @@ -341,7 +343,7 @@ const useMapToProps = ({ costType, currency, query }): InstancesStateProps => {
...(query.filter || baseQuery.filter),
resolution: 'monthly',
time_scope_units: 'month',
time_scope_value: -1,
time_scope_value: timeScopeValue !== undefined ? timeScopeValue : -1,
},
filter_by: {
// Add filters here to apply logical OR/AND
Expand Down
Loading
Loading