Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deployment commit for prod-stable #3547

Merged
merged 27 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
95c72ee
Using Optimizations badge from Koku-ui microfrontend
dlabrecq Oct 11, 2023
bd67b63
Using Optimizations summary from Koku-ui microfrontend
dlabrecq Oct 17, 2023
b4e8185
Using Optimizations details from Koku-ui microfrontend
dlabrecq Oct 19, 2023
50ba6f3
Using Optimizations breakdown from Koku-ui microfrontend
dlabrecq Oct 21, 2023
73bf7c6
Removed ROS from Redux store
dlabrecq Oct 24, 2023
5c9f1f8
Using Optimizations link from Koku-ui microfrontend
dlabrecq Oct 24, 2023
a1c31a0
Add link state
dlabrecq Oct 30, 2023
677ee97
Fix Jest test transform for uuid
dlabrecq Oct 31, 2023
2fc111d
Update npm scripts to run mfe
dlabrecq Nov 20, 2023
6929d7a
Merge pull request #3531 from dlabrecq/fed-mods
dlabrecq Nov 21, 2023
a58b85f
Force container build
dlabrecq Nov 22, 2023
9d1ff71
Merge pull request #3532 from dlabrecq/force
dlabrecq Nov 22, 2023
e510cfa
(chore): Bump @types/jest from 29.5.8 to 29.5.10
dependabot[bot] Nov 27, 2023
e077463
(chore): Bump @unleash/proxy-client-react from 4.1.0 to 4.1.1
dependabot[bot] Nov 27, 2023
423a04d
(chore): Bump @types/react-redux from 7.1.30 to 7.1.31
dependabot[bot] Nov 27, 2023
cd25691
Project filter should be shown for optimization details page
dlabrecq Nov 28, 2023
a43158b
Merge pull request #3540 from project-koku/dependabot_npm_and_yarn_ma…
dlabrecq Nov 28, 2023
ad094ce
Merge pull request #3534 from project-koku/dependabot_npm_and_yarn_ma…
dlabrecq Nov 28, 2023
09d558d
Merge pull request #3535 from project-koku/dependabot_npm_and_yarn_ma…
dlabrecq Nov 28, 2023
67021b5
Dependency updates
dlabrecq Nov 28, 2023
70b5aea
Merge pull request #3541 from dlabrecq/4325-project
dlabrecq Nov 28, 2023
2ce72a2
Merge pull request #3544 from dlabrecq/deps
dlabrecq Nov 28, 2023
0f71720
Merge remote-tracking branch 'origin/main' into stage-stable
dlabrecq Nov 28, 2023
c437775
Merge pull request #3545 from project-koku/release_stage-stable.3745
dlabrecq Nov 28, 2023
6f92e01
Merge remote-tracking branch 'origin/stage-stable' into prod-beta
dlabrecq Nov 28, 2023
ed24113
Merge pull request #3546 from project-koku/release_prod-beta.5032
dlabrecq Nov 28, 2023
cc9e3b8
Merge remote-tracking branch 'origin/prod-beta' into prod-stable
dlabrecq Nov 28, 2023
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import global_BackgroundColor_light_100 from '@patternfly/react-tokens/dist/js/global_BackgroundColor_light_100';
import global_spacer_lg from '@patternfly/react-tokens/dist/js/global_spacer_lg';
import global_spacer_md from '@patternfly/react-tokens/dist/js/global_spacer_md';
import type React from 'react';

export const styles = {
alertContainer: {
marginBottom: global_spacer_lg.value,
},
codeBlock: {
display: 'flex',
},
container: {
minHeight: '100vh',
},
currentActions: {
height: '36px',
},
pagination: {
backgroundColor: global_BackgroundColor_light_100.value,
paddingBottom: global_spacer_md.value,
paddingTop: global_spacer_md.value,
},
} as { [className: string]: React.CSSProperties };
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import './optimizationsBreakdown.scss';

import { Alert, List, ListItem, PageSection } from '@patternfly/react-core';
import type { Query } from 'api/queries/query';
import { parseQuery } from 'api/queries/query';
import type { RosQuery } from 'api/queries/rosQuery';
import type { RecommendationItem, RecommendationReportData } from 'api/ros/recommendations';
import { RosPathsType, RosType } from 'api/ros/ros';
import type { AxiosError } from 'axios';
import messages from 'locales/messages';
import React, { useEffect, useState } from 'react';
import { useIntl } from 'react-intl';
import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';
import type { AnyAction } from 'redux';
import type { ThunkDispatch } from 'redux-thunk';
import { Loading } from 'routes/components/page/loading';
import type { RootState } from 'store';
import { FetchStatus } from 'store/common';
import { rosActions, rosSelectors } from 'store/ros';
import { breadcrumbLabelKey } from 'utils/props';
import { getNotifications, hasRecommendation } from 'utils/recomendations';
import type { RouterComponentProps } from 'utils/router';

import { styles } from './optimizationsBreakdown.styles';
import { OptimizationsBreakdownConfiguration } from './optimizationsBreakdownConfiguration';
import { OptimizationsBreakdownHeader } from './optimizationsBreakdownHeader';

interface OptimizationsBreakdownOwnProps extends RouterComponentProps {
id?: string;
}

interface OptimizationsBreakdownStateProps {
breadcrumbLabel?: string;
report?: RecommendationReportData;
reportError?: AxiosError;
reportFetchStatus?: FetchStatus;
reportQueryString?: string;
}

export interface OptimizationsBreakdownMapProps {
query?: RosQuery;
}

type OptimizationsBreakdownProps = OptimizationsBreakdownOwnProps & OptimizationsBreakdownStateProps;

// eslint-disable-next-line no-shadow
export const enum Interval {
short_term = 'short_term', // last 24 hrs
medium_term = 'medium_term', // last 7 days
long_term = 'long_term', // last 15 days
}

const reportType = RosType.ros as any;
const reportPathsType = RosPathsType.recommendation as any;

const OptimizationsBreakdown: React.FC<OptimizationsBreakdownProps> = () => {
const { breadcrumbLabel, report, reportFetchStatus } = useMapToProps();
const intl = useIntl();
const location = useLocation();

const getDefaultTerm = () => {
let result = Interval.short_term;
if (!report?.recommendations?.duration_based) {
return result;
}

const recommendation = report.recommendations.duration_based;
if (hasRecommendation(recommendation.short_term)) {
result = Interval.short_term;
} else if (hasRecommendation(recommendation.medium_term)) {
result = Interval.medium_term;
} else if (hasRecommendation(recommendation.long_term)) {
result = Interval.long_term;
}
return result as Interval;
};

const [currentInterval, setCurrentInterval] = useState(getDefaultTerm());

const getAlert = () => {
let notifications;
if (report?.recommendations?.duration_based?.[currentInterval]) {
notifications = getNotifications(report.recommendations.duration_based[currentInterval]);
}

if (!notifications) {
return null;
}

return (
<div style={styles.alertContainer}>
<Alert isInline variant="warning" title={intl.formatMessage(messages.notificationsAlertTitle)}>
<List>
{notifications.map((notification, index) => (
<ListItem key={index}>{notification.message}</ListItem>
))}
</List>
</Alert>
</div>
);
};

const getRecommendationTerm = (): RecommendationItem => {
if (!report) {
return undefined;
}

let result;
switch (currentInterval) {
case Interval.short_term:
result = report.recommendations.duration_based.short_term;
break;
case Interval.medium_term:
result = report.recommendations.duration_based.medium_term;
break;
case Interval.long_term:
result = report.recommendations.duration_based.long_term;
break;
}
return result;
};

const handleOnSelected = (value: Interval) => {
setCurrentInterval(value);
};

const isLoading = reportFetchStatus === FetchStatus.inProgress;

return (
<div style={styles.container}>
<OptimizationsBreakdownHeader
breadcrumbLabel={breadcrumbLabel}
breadcrumbPath={
location.state && location.state.optimizations ? location.state.optimizations.breadcrumbPath : undefined
}
currentInterval={currentInterval}
isDisabled={isLoading}
onSelected={handleOnSelected}
report={report}
/>
<PageSection isFilled>
{isLoading ? (
<Loading
body={intl.formatMessage(messages.optimizationsLoadingStateDesc)}
heading={intl.formatMessage(messages.optimizationsLoadingStateTitle)}
/>
) : (
<>
{getAlert()}
<OptimizationsBreakdownConfiguration term={getRecommendationTerm()} />
</>
)}
</PageSection>
</div>
);
};

const useQueryFromRoute = () => {
const location = useLocation();
return parseQuery<Query>(location.search);
};

// eslint-disable-next-line no-empty-pattern
const useMapToProps = (): OptimizationsBreakdownStateProps => {
const dispatch: ThunkDispatch<RootState, any, AnyAction> = useDispatch();
const queryFromRoute = useQueryFromRoute();

const reportQueryString = queryFromRoute ? queryFromRoute.id : '';
const report: any = useSelector((state: RootState) =>
rosSelectors.selectRos(state, reportPathsType, reportType, reportQueryString)
);
const reportFetchStatus = useSelector((state: RootState) =>
rosSelectors.selectRosFetchStatus(state, reportPathsType, reportType, reportQueryString)
);
const reportError = useSelector((state: RootState) =>
rosSelectors.selectRosError(state, reportPathsType, reportType, reportQueryString)
);

useEffect(() => {
if (!reportError && reportFetchStatus !== FetchStatus.inProgress) {
dispatch(rosActions.fetchRosReport(reportPathsType, reportType, reportQueryString));
}
}, [reportQueryString]);

return {
breadcrumbLabel: queryFromRoute[breadcrumbLabelKey],
report,
reportError,
reportFetchStatus,
reportQueryString,
};
};

export default OptimizationsBreakdown;
Loading
Loading