Skip to content

Commit

Permalink
Ensure tag keys are available for given date range
Browse files Browse the repository at this point in the history
  • Loading branch information
dlabrecq committed Dec 10, 2024
1 parent f691878 commit a740cdc
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 84 deletions.
10 changes: 7 additions & 3 deletions src/routes/components/dataToolbar/dataToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ export class DataToolbarBase extends React.Component<DataToolbarProps, DataToolb
) {
this.setState(() => {
const filters = getActiveFilters(query);
return categoryOptions !== prevProps.categoryOptions || prevProps.groupBy !== groupBy
return prevProps.groupBy !== groupBy ||
!isEqual(tagReport, prevProps.tagReport) ||
!isEqual(categoryOptions, prevProps.categoryOptions)
? {
categoryInput: '',
costCategoryKeyValueInput: '',
Expand Down Expand Up @@ -582,9 +584,9 @@ export class DataToolbarBase extends React.Component<DataToolbarProps, DataToolb
onTagValueSelect: this.handleOnTagValueSelect,
onTagValueInput: this.handleOnTagValueInput,
onTagValueInputChange: this.handleOnTagValueInputChange,
tagKeyValueInput,
tagKeyOption,
tagPathsType,
tagKeyValueInput,
});
};

Expand Down Expand Up @@ -739,8 +741,10 @@ export class DataToolbarBase extends React.Component<DataToolbarProps, DataToolb
showFilter,
showPlatformCosts,
style,
query,
tagReport,
} = this.props;

const options = categoryOptions ? categoryOptions : getDefaultCategoryOptions();
const filteredOptions = options.filter(
option => option.key !== awsCategoryKey && option.key !== tagKey && option.key !== orgUnitIdKey
Expand All @@ -766,7 +770,7 @@ export class DataToolbarBase extends React.Component<DataToolbarProps, DataToolb
this.getCostCategoryValueSelectComponent(option)
)}
{this.getTagKeySelectComponent()}
{getTagKeyOptions(tagReport).map(option => this.getTagValueSelect(option))}
{getTagKeyOptions(tagReport, query).map(option => this.getTagValueSelect(option))}
{this.getOrgUnitSelectComponent()}
{filteredOptions.map(option => this.getCategoryInputComponent(option))}
{filteredOptions.map(option => this.getCustomSelectComponent(option))}
Expand Down
78 changes: 75 additions & 3 deletions src/routes/components/dataToolbar/utils/tags.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ToolbarChipGroup } from '@patternfly/react-core';
import { ToolbarFilter, ToolbarItem } from '@patternfly/react-core';
import type { Query } from 'api/queries/query';
import type { Tag, TagPathsType } from 'api/tags/tag';
import { intl } from 'components/i18n';
import messages from 'locales/messages';
Expand Down Expand Up @@ -35,7 +36,7 @@ export const getTagKeySelect = ({
return null;
}

const selectOptions = getTagKeyOptions(tagReport, true) as SelectWrapperOption[];
const selectOptions = getTagKeyOptionsFromReport(tagReport, true) as SelectWrapperOption[];

return (
<ToolbarItem>
Expand All @@ -53,7 +54,78 @@ export const getTagKeySelect = ({
);
};

// Ensure tag keys are available for given date range
//
// Note: It's possible the user applied a tag filter which is no longer available in a new date range.
// For example, when switching the date range between current and previous months. Tags may only be available in the
// current month and vice versa.
//
// The problem is that we obtain a list of tag keys from the tag report, in order to show the currently applied filters
// using PatternFly filter chips. If an applied filter is not available in the tag report, then the associated
// filter chip will not be shown and users cannot clear that filter.
//
// As a workaround, we can use the filter_by query params to discover any missing tag keys. This represents the
// previously applied filters, which we combine with keys from the tag report.
export const getTagKeyOptions = (
tagReport: Tag,
query: Query,
isSelectWrapperOption = false
): ToolbarChipGroup[] | SelectWrapperOption[] => {
const options = [];
const reportOptions = getTagKeyOptionsFromReport(tagReport, isSelectWrapperOption);
const queryOptions = getTagKeyOptionsFromQuery(query, isSelectWrapperOption);

const isTagKeyEqual = (a, b) => {
if (isSelectWrapperOption) {
return a.value === b.value;
} else {
return a.name === b.name;
}
};

for (const reportoption of reportOptions) {
if (!options.find(option => isTagKeyEqual(option, reportoption))) {
options.push(reportoption);
}
}
for (const queryOption of queryOptions) {
if (!options.find(option => isTagKeyEqual(option, queryOption))) {
options.push(queryOption);
}
}
return options;
};

export const getTagKeyOptionsFromQuery = (
query: Query,
isSelectWrapperOption = false
): ToolbarChipGroup[] | SelectWrapperOption[] => {
const options = [];

if (!query?.filter_by) {
return options;
}

for (const filter of Object.keys(query.filter_by)) {
if (filter.indexOf(tagPrefix) !== -1) {
const key = filter.substring(tagPrefix.length);
options.push(
isSelectWrapperOption
? {
toString: () => key, // Tag keys not localized
value: key,
}
: {
key,
name: key, // Tag keys not localized
}
);
}
}
return options;
};

export const getTagKeyOptionsFromReport = (
tagReport: Tag,
isSelectWrapperOption = false
): ToolbarChipGroup[] | SelectWrapperOption[] => {
Expand Down Expand Up @@ -112,9 +184,9 @@ export const getTagValueSelect = ({
onTagValueSelect,
onTagValueInput,
onTagValueInputChange,
tagKeyValueInput,
tagKeyOption,
tagPathsType,
tagKeyValueInput,
}: {
currentCategory?: string;
currentTagKey?: string;
Expand All @@ -124,9 +196,9 @@ export const getTagValueSelect = ({
onTagValueSelect?: (event: any, selection) => void;
onTagValueInput?: (event: any) => void;
onTagValueInputChange?: (value: string) => void;
tagKeyValueInput?: string;
tagKeyOption?: ToolbarChipGroup;
tagPathsType?: TagPathsType;
tagKeyValueInput?: string;
}) => {
// Todo: categoryName workaround for https://issues.redhat.com/browse/COST-2094
const categoryName = {
Expand Down
4 changes: 2 additions & 2 deletions src/routes/components/groupBy/groupBy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class GroupByBase extends React.Component<GroupByProps, GroupByState> {
prevProps.startDate !== startDate ||
prevProps.timeScopeValue !== timeScopeValue
) {
let options = {};
let options;
if (prevProps.perspective !== perspective) {
options = {
isGroupByCostCategoryVisible: false,
Expand All @@ -141,7 +141,7 @@ class GroupByBase extends React.Component<GroupByProps, GroupByState> {
}
if (prevProps.timeScopeValue !== timeScopeValue && this.getCurrentGroupBy() !== tagKey) {
options = {
...options,
...(options && options),
isGroupByTagVisible: false,
};
}
Expand Down
19 changes: 9 additions & 10 deletions src/routes/details/awsDetails/detailsToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,21 @@ export class DetailsToolbarBase extends React.Component<DetailsToolbarProps, Det
}

public componentDidUpdate(prevProps: DetailsToolbarProps) {
const { orgReport, query, resourceReport, tagReport } = this.props;
const { orgReport, query, resourceReport, tagQueryString, tagReport } = this.props;

if (
!isEqual(orgReport, prevProps.orgReport) ||
!isEqual(resourceReport, prevProps.resourceReport) ||
!isEqual(tagReport, prevProps.tagReport)
) {
this.setState(
{
categoryOptions: this.getCategoryOptions(),
},
() => {
this.updateReport();
}
);
} else if (query && !isEqual(query, prevProps.query)) {
this.setState({
categoryOptions: this.getCategoryOptions(),
});
}
if (
(query && !isEqual(query, prevProps.query)) ||
(tagQueryString && !isEqual(tagQueryString, prevProps.tagQueryString))
) {
this.updateReport();
}
}
Expand Down
19 changes: 9 additions & 10 deletions src/routes/details/azureDetails/detailsToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,17 @@ export class DetailsToolbarBase extends React.Component<DetailsToolbarProps, Det
}

public componentDidUpdate(prevProps: DetailsToolbarProps) {
const { query, tagReport } = this.props;
const { query, tagQueryString, tagReport } = this.props;

if (!isEqual(tagReport, prevProps.tagReport)) {
this.setState(
{
categoryOptions: this.getCategoryOptions(),
},
() => {
this.updateReport();
}
);
} else if (query && !isEqual(query, prevProps.query)) {
this.setState({
categoryOptions: this.getCategoryOptions(),
});
}
if (
(query && !isEqual(query, prevProps.query)) ||
(tagQueryString && !isEqual(tagQueryString, prevProps.tagQueryString))
) {
this.updateReport();
}
}
Expand Down
19 changes: 9 additions & 10 deletions src/routes/details/gcpDetails/detailsToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,17 @@ export class DetailsToolbarBase extends React.Component<DetailsToolbarProps, Det
}

public componentDidUpdate(prevProps: DetailsToolbarProps) {
const { query, tagReport } = this.props;
const { query, tagQueryString, tagReport } = this.props;

if (!isEqual(tagReport, prevProps.tagReport)) {
this.setState(
{
categoryOptions: this.getCategoryOptions(),
},
() => {
this.updateReport();
}
);
} else if (query && !isEqual(query, prevProps.query)) {
this.setState({
categoryOptions: this.getCategoryOptions(),
});
}
if (
(query && !isEqual(query, prevProps.query)) ||
(tagQueryString && !isEqual(tagQueryString, prevProps.tagQueryString))
) {
this.updateReport();
}
}
Expand Down
19 changes: 9 additions & 10 deletions src/routes/details/ibmDetails/detailsToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,17 @@ export class DetailsToolbarBase extends React.Component<DetailsToolbarProps, Det
}

public componentDidUpdate(prevProps: DetailsToolbarProps) {
const { query, tagReport } = this.props;
const { query, tagQueryString, tagReport } = this.props;

if (!isEqual(tagReport, prevProps.tagReport)) {
this.setState(
{
categoryOptions: this.getCategoryOptions(),
},
() => {
this.updateReport();
}
);
} else if (query && !isEqual(query, prevProps.query)) {
this.setState({
categoryOptions: this.getCategoryOptions(),
});
}
if (
(query && !isEqual(query, prevProps.query)) ||
(tagQueryString && !isEqual(tagQueryString, prevProps.tagQueryString))
) {
this.updateReport();
}
}
Expand Down
19 changes: 9 additions & 10 deletions src/routes/details/ociDetails/detailsToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,17 @@ export class DetailsToolbarBase extends React.Component<DetailsToolbarProps, Det
}

public componentDidUpdate(prevProps: DetailsToolbarProps) {
const { query, tagReport } = this.props;
const { query, tagQueryString, tagReport } = this.props;

if (!isEqual(tagReport, prevProps.tagReport)) {
this.setState(
{
categoryOptions: this.getCategoryOptions(),
},
() => {
this.updateReport();
}
);
} else if (query && !isEqual(query, prevProps.query)) {
this.setState({
categoryOptions: this.getCategoryOptions(),
});
}
if (
(query && !isEqual(query, prevProps.query)) ||
(tagQueryString && !isEqual(tagQueryString, prevProps.tagQueryString))
) {
this.updateReport();
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/routes/details/ocpDetails/detailsToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,17 @@ export class DetailsToolbarBase extends React.Component<DetailsToolbarProps, Det
}

public componentDidUpdate(prevProps: DetailsToolbarProps) {
const { query, tagReport } = this.props;
const { query, tagQueryString, tagReport } = this.props;

if (!isEqual(tagReport, prevProps.tagReport)) {
this.setState(
{
categoryOptions: this.getCategoryOptions(),
},
() => {
this.updateReport();
}
);
} else if (query && !isEqual(query, prevProps.query)) {
this.setState({
categoryOptions: this.getCategoryOptions(),
});
}
if (
(query && !isEqual(query, prevProps.query)) ||
(tagQueryString && !isEqual(tagQueryString, prevProps.tagQueryString))
) {
this.updateReport();
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/routes/details/rhelDetails/detailsToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,17 @@ export class DetailsToolbarBase extends React.Component<DetailsToolbarProps> {
}

public componentDidUpdate(prevProps: DetailsToolbarProps) {
const { query, tagReport } = this.props;
const { query, tagQueryString, tagReport } = this.props;

if (!isEqual(tagReport, prevProps.tagReport)) {
this.setState(
{
categoryOptions: this.getCategoryOptions(),
},
() => {
this.updateReport();
}
);
} else if (query && !isEqual(query, prevProps.query)) {
this.setState({
categoryOptions: this.getCategoryOptions(),
});
}
if (
(query && !isEqual(query, prevProps.query)) ||
(tagQueryString && !isEqual(tagQueryString, prevProps.tagQueryString))
) {
this.updateReport();
}
}
Expand Down
Loading

0 comments on commit a740cdc

Please sign in to comment.