Skip to content

Commit 36cfa13

Browse files
authored
Add Dark-Mode Support for Cost management (#1885)
1 parent cb437b4 commit 36cfa13

6 files changed

Lines changed: 104 additions & 11 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { useTheme } from '@material-ui/core/styles';
18+
19+
/**
20+
* Hook that returns the appropriate background color based on the current theme mode.
21+
* @returns Object with backgroundColor and filterTableBackgroundColor strings
22+
*/
23+
export const useThemeBackgroundColor = (): {
24+
backgroundColor: string;
25+
filterTableBackgroundColor: string;
26+
} => {
27+
const theme = useTheme();
28+
const isDarkMode = (theme.palette as any).mode === 'dark';
29+
30+
return {
31+
backgroundColor: isDarkMode ? '#292929' : '#FFFFFF',
32+
filterTableBackgroundColor: isDarkMode ? '#262626' : '#F2F2F2',
33+
};
34+
};

workspaces/redhat-resource-optimization/plugins/redhat-resource-optimization/src/pages/openshift/OpenShiftPage.tsx

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import Typography from '@material-ui/core/Typography';
2525
import { BasePage } from '../../components/BasePage';
2626
import { PageLayout } from '../../components/PageLayout';
2727
import { Filters } from './components/Filters';
28-
import { Divider } from '@material-ui/core';
28+
import { Divider, useTheme } from '@material-ui/core';
2929
import { PageHeader } from './components/PageHeader';
3030
import { TableToolbar } from './components/TableToolbar';
3131
import { useApi } from '@backstage/core-plugin-api';
@@ -57,6 +57,31 @@ interface ProjectCost {
5757
supplementaryCostPercentage: number;
5858
}
5959

60+
/**
61+
* Generates date range text based on time range selection
62+
* @param timeRange - 'month-to-date' or 'previous-month'
63+
* @returns Formatted string like "December 1-3" or "November 1-30"
64+
*/
65+
function getDateRangeText(timeRange: string): string {
66+
const now = new Date();
67+
const currentMonth = now.getMonth();
68+
const currentYear = now.getFullYear();
69+
const currentDay = now.getDate();
70+
71+
if (timeRange === 'month-to-date') {
72+
// Current month: MONTH 1-<CURRENT_DAY>
73+
const monthName = now.toLocaleString('en-US', { month: 'long' });
74+
return `${monthName} 1-${currentDay}`;
75+
}
76+
// Previous month: PREVIOUS_MONTH 1-<LAST_DAY>
77+
const prevMonth = currentMonth === 0 ? 11 : currentMonth - 1;
78+
const prevYear = currentMonth === 0 ? currentYear - 1 : currentYear;
79+
const prevMonthDate = new Date(prevYear, prevMonth + 1, 0); // Last day of previous month
80+
const lastDay = prevMonthDate.getDate();
81+
const monthName = prevMonthDate.toLocaleString('en-US', { month: 'long' });
82+
return `${monthName} 1-${lastDay}`;
83+
}
84+
6085
/** @public */
6186
export function OpenShiftPage() {
6287
const api = useApi(optimizationsApiRef);
@@ -82,6 +107,8 @@ export function OpenShiftPage() {
82107
useState(true);
83108
const [showInfrastructureCost, setShowInfrastructureCost] = useState(false);
84109
const [showSupplementaryCost, setShowSupplementaryCost] = useState(false);
110+
const theme = useTheme();
111+
const isDarkMode = (theme.palette as any).mode === 'dark';
85112

86113
// Fetch tags on first load
87114
useAsync(async () => {
@@ -391,6 +418,12 @@ export function OpenShiftPage() {
391418
selectedRows.size < displayData.projects.length;
392419

393420
const columns = useMemo<TableColumn<ProjectCost>[]>(() => {
421+
const getChangeColor = (change: number) => {
422+
if (change > 0) return '#d32f2f';
423+
if (isDarkMode) return '#4BB543';
424+
return '#2e7d32';
425+
};
426+
394427
const cols: TableColumn<ProjectCost>[] = [
395428
{
396429
title: (
@@ -482,7 +515,7 @@ export function OpenShiftPage() {
482515
<div>
483516
<div
484517
style={{
485-
color: data.monthOverMonthChange > 0 ? '#d32f2f' : '#2e7d32',
518+
color: getChangeColor(data.monthOverMonthChange),
486519
}}
487520
>
488521
{Math.abs(data.monthOverMonthChange).toFixed(2)}%
@@ -493,7 +526,7 @@ export function OpenShiftPage() {
493526
data.monthOverMonthValue,
494527
displayData?.currencyCode || '',
495528
)}{' '}
496-
for January 1-11
529+
for {getDateRangeText(timeRange)}
497530
</div>
498531
</div>
499532
),
@@ -561,8 +594,14 @@ export function OpenShiftPage() {
561594
sorting: false,
562595
render: () => (
563596
<div style={{ display: 'flex', gap: '8px' }}>
564-
<DownloadIconButton label="CSV" variant="black" />
565-
<DownloadIconButton label="JSON" variant="black" />
597+
<DownloadIconButton
598+
label="CSV"
599+
variant={isDarkMode ? 'white' : 'black'}
600+
/>
601+
<DownloadIconButton
602+
label="JSON"
603+
variant={isDarkMode ? 'white' : 'black'}
604+
/>
566605
</div>
567606
),
568607
});
@@ -579,6 +618,8 @@ export function OpenShiftPage() {
579618
showMonthOverMonthChange,
580619
showInfrastructureCost,
581620
showSupplementaryCost,
621+
timeRange,
622+
isDarkMode,
582623
]);
583624

584625
const handleOrderChange = useCallback(

workspaces/redhat-resource-optimization/plugins/redhat-resource-optimization/src/pages/openshift/components/AutocompleteComponent.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ import {
2525
AutocompleteChangeDetails,
2626
AutocompleteChangeReason,
2727
} from '@material-ui/lab';
28+
import { useThemeBackgroundColor } from '../../../hooks/useThemeBackgroundColor';
2829

2930
const useAutocompleteStyles = makeStyles(
3031
{
3132
root: {},
3233
label: {},
33-
input: { backgroundColor: '#ffffff' },
34+
input: { backgroundColor: 'transparent' },
3435
fullWidth: { width: '100%' },
3536
},
3637
{ name: 'AutocompleteComponent' },
@@ -77,6 +78,7 @@ type AutocompleteComponentProps = SingleProps | MultipleProps;
7778
export function AutocompleteComponent(props: AutocompleteComponentProps) {
7879
const classes = useAutocompleteStyles();
7980
const { label, options, placeholder, className } = props;
81+
const { backgroundColor } = useThemeBackgroundColor();
8082

8183
return (
8284
<Box className={className ?? classes.root} pb={1} pt={1}>
@@ -111,9 +113,9 @@ export function AutocompleteComponent(props: AutocompleteComponentProps) {
111113
renderInput={params => (
112114
<TextField
113115
{...params}
114-
className={classes.input}
115116
variant="outlined"
116117
placeholder={placeholder}
118+
style={{ backgroundColor }}
117119
/>
118120
)}
119121
size="medium"

workspaces/redhat-resource-optimization/plugins/redhat-resource-optimization/src/pages/openshift/components/DownloadIconButton.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,18 @@ import React from 'react';
1919

2020
type DownloadIconButtonProps = {
2121
label: string;
22-
variant: 'gray' | 'black';
22+
variant: 'gray' | 'black' | 'white';
23+
};
24+
25+
const getColor = (variant: 'gray' | 'black' | 'white') => {
26+
if (variant === 'gray') return '#C7C7C7';
27+
if (variant === 'black') return '#000000';
28+
if (variant === 'white') return '#FFFFFF';
29+
return '#C7C7C7';
2330
};
2431

2532
export function DownloadIconButton(props: Readonly<DownloadIconButtonProps>) {
26-
const color = props.variant === 'gray' ? '#C7C7C7' : '#000000';
33+
const color = getColor(props.variant);
2734

2835
return (
2936
<div

workspaces/redhat-resource-optimization/plugins/redhat-resource-optimization/src/pages/openshift/components/Filters.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { useApi } from '@backstage/core-plugin-api';
2525
import { optimizationsApiRef } from '../../../apis';
2626
import useAsync from 'react-use/lib/useAsync';
2727
import debounce from 'lodash/debounce';
28+
import { useThemeBackgroundColor } from '../../../hooks/useThemeBackgroundColor';
2829

2930
const useFiltersStyles = makeStyles(
3031
theme => ({
@@ -102,6 +103,7 @@ export function Filters(props: FiltersProps) {
102103
const classes = useFiltersStyles();
103104
const api = useApi(optimizationsApiRef);
104105

106+
const { filterTableBackgroundColor } = useThemeBackgroundColor();
105107
// State for search input and debounced search
106108
const [searchInput, setSearchInput] = useState<string>('');
107109
const [debouncedSearch, setDebouncedSearch] = useState<string>('');
@@ -351,7 +353,11 @@ export function Filters(props: FiltersProps) {
351353
{/* Filter table by */}
352354
<div className={classes.filterSection}>
353355
<div
354-
style={{ backgroundColor: '#F2F2F2', padding: 16, borderRadius: 8 }}
356+
style={{
357+
backgroundColor: filterTableBackgroundColor,
358+
padding: 16,
359+
borderRadius: 8,
360+
}}
355361
>
356362
<div style={{ fontWeight: 'bold', marginBottom: '8px' }}>
357363
Filter table by

workspaces/redhat-resource-optimization/plugins/redhat-resource-optimization/src/pages/openshift/components/SelectComponent.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import FormControl from '@material-ui/core/FormControl';
2222
import Select from '@material-ui/core/Select';
2323
import MenuItem from '@material-ui/core/MenuItem';
2424
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
25+
import { useThemeBackgroundColor } from '../../../hooks/useThemeBackgroundColor';
2526

2627
const useSelectStyles = makeStyles(
2728
{
@@ -30,7 +31,7 @@ const useSelectStyles = makeStyles(
3031
formControl: {
3132
width: '100%',
3233
marginTop: 5,
33-
backgroundColor: '#ffffff',
34+
backgroundColor: 'transparent',
3435
},
3536
},
3637
{
@@ -55,6 +56,7 @@ type SelectProps = {
5556
/** @public */
5657
export function SelectComponent(props: SelectProps) {
5758
const classes = useSelectStyles();
59+
const { backgroundColor } = useThemeBackgroundColor();
5860
const {
5961
label,
6062
options,
@@ -73,6 +75,7 @@ export function SelectComponent(props: SelectProps) {
7375
className={classes.formControl}
7476
variant="outlined"
7577
hiddenLabel
78+
style={{ backgroundColor }}
7679
>
7780
<Select
7881
displayEmpty

0 commit comments

Comments
 (0)