Skip to content

Commit

Permalink
fix: Update bundgets data structure
Browse files Browse the repository at this point in the history
  • Loading branch information
vio committed Apr 9, 2022
1 parent 2228a38 commit 7a66a1e
Show file tree
Hide file tree
Showing 12 changed files with 458 additions and 316 deletions.
34 changes: 12 additions & 22 deletions packages/ui/src/components/budget-info/budget-info.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from 'react';
import cx from 'classnames';
import PropTypes from 'prop-types';
import { InsightType } from '@bundle-stats/utils';
import * as budgetsInsightsTransformer from '@bundle-stats/utils/lib-esm/transformers/budgets-insights';

import { Icon } from '../../ui/icon';
import { Tooltip } from '../../ui/tooltip';
Expand All @@ -24,38 +23,29 @@ const INSIGHT_TYPE_MAP = {
},
};

export const BudgetInfo = ({ className = '', metricId, budgetInsight }) => {
const budgetInsightInfo = budgetsInsightsTransformer.getInfo(metricId, budgetInsight);
const { className: insightTypeClassName, glyph } = INSIGHT_TYPE_MAP[budgetInsightInfo.type];
export const BudgetInfo = ({ className = '', budgetInsight }) => {
const { className: insightTypeClassName, glyph } = INSIGHT_TYPE_MAP[budgetInsight.type];

const rootClassName = cx(css.root, insightTypeClassName, className);
const { data: messageData } = budgetInsightInfo.message;

return (
<Tooltip
className={rootClassName}
title={
<>
<strong>{messageData.metricLabel}</strong>
{` value (`}
<strong>{messageData.currentValue}</strong>
{`) is ${messageData.diffLabel} `}
<strong>{messageData.budgetValue}</strong>
{` budget `}
</>
}
>
<Tooltip className={rootClassName} title={budgetInsight.message.text}>
<Icon className={css.icon} glyph={glyph} size="medium" />
</Tooltip>
);
};

BudgetInfo.propTypes = {
metricId: PropTypes.string.isRequired,
budgetInsight: PropTypes.shape({
currentValue: PropTypes.number,
budgetValue: PropTypes.number,
failed: PropTypes.bool,
type: PropTypes.string,
message: PropTypes.shape({
text: PropTypes.string,
}),
data: PropTypes.shape({
currentValue: PropTypes.number,
budgetValue: PropTypes.number,
failed: PropTypes.bool,
}),
}).isRequired,
className: PropTypes.string,
};
Expand Down
39 changes: 27 additions & 12 deletions packages/ui/src/components/budget-info/budget-info.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,48 @@ stories.addDecorator(getWrapperDecorator());

stories.add('default', () => (
<BudgetInfo
metricId="webpack.assetCount"
budgetInsight={{
budgetValue: 300,
currentValue: 250,
failed: false,
type: 'SUCCESS',
message: {
text: 'Metric is under the budget',
},
data: {
budgetValue: 300,
currentValue: 250,
failed: false,
},
}}
/>
));

stories.add('error', () => (
<BudgetInfo
metricId="webpack.assetCount"
budgetInsight={{
budgetValue: 300,
currentValue: 350,
failed: true,
type: 'ERROR',
message: {
text: 'Metric is over the budget',
},
data: {
budgetValue: 300,
currentValue: 250,
failed: false,
},
}}
/>
));

stories.add('warning', () => (
<BudgetInfo
metricId="webpack.assetCount"
budgetInsight={{
budgetValue: 300,
currentValue: 300,
failed: false,
type: 'WARNING',
message: {
text: 'Metric is equal the budget',
},
data: {
budgetValue: 300,
currentValue: 250,
failed: false,
},
}}
/>
));
100 changes: 55 additions & 45 deletions packages/ui/src/components/budget-insights/budget-insights.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import { METRIC_COMPONENT_LINKS } from '@bundle-stats/utils';
import * as budgetsInsightsTransformer from '@bundle-stats/utils/lib-esm/transformers/budgets-insights';

import { Box } from '../../layout/box';
import { Stack } from '../../layout/stack';
Expand All @@ -13,30 +12,28 @@ import { ComponentLink } from '../component-link';
import css from './budget-insights.module.css';

const Budget = (props) => {
const { className, metricId, budgetInsight, CustomLink } = props;
const { className, metricId, budget, CustomLink } = props;
const componentLinkOptions = METRIC_COMPONENT_LINKS.get(metricId);
const budgetInsightInfo = budgetsInsightsTransformer.getInfo(metricId, budgetInsight);
const { data: messageData } = budgetInsightInfo.message;

return (
<CustomLink className={cx(css.budget, className)} {...componentLinkOptions?.link}>
<strong>{messageData.metricLabel}</strong>
{` value (`}
<strong>{messageData.currentValue}</strong>
{`) is ${messageData.diffLabel} `}
<strong>{messageData.budgetValue}</strong>
{` budget `}
{budget.message.text}
</CustomLink>
);
};

Budget.propTypes = {
className: PropTypes.string,
metricId: PropTypes.string.isRequired,
budgetInsight: PropTypes.shape({
currentValue: PropTypes.number.isRequired,
budgetValue: PropTypes.number.isRequired,
failed: PropTypes.bool.isRequired,
budget: PropTypes.shape({
message: PropTypes.shape({
text: PropTypes.string,
}),
data: PropTypes.shape({
currentValue: PropTypes.number.isRequired,
budgetValue: PropTypes.number.isRequired,
failed: PropTypes.bool.isRequired,
}),
}).isRequired,
CustomLink: PropTypes.elementType.isRequired,
};
Expand Down Expand Up @@ -103,44 +100,57 @@ BudgetsGroup.defaultProps = {
className: '',
};

export const BudgetInsights = (props) => {
const { className, source, budgets, CustomLink } = props;
const BUDGET_ALERT_KIND = new Map([
['ERROR', 'danger'],
['WARNING', 'warning'],
['SUCCESS', 'success'],
]);

const [failedBudgets, passedBudgets] = useMemo(() => {
const passed = [];
const failed = [];
const BUDGET_ICON = new Map([
['ERROR', Icon.ICONS.ALERT_CIRCLE],
['WARNING', Icon.ICONS.WARNING],
['SUCCESS', Icon.ICONS.CHECK_CIRCLE],
]);

Object.entries(budgets).forEach(([key, budget]) => {
if (budget.failed) {
failed.push([key, budget]);
} else {
passed.push([key, budget]);
}
});
export const BudgetInsights = (props) => {
const { className, source, budgets, CustomLink } = props;
const [showBudgets, setShowBudgets] = useState(false);

return [failed, passed];
}, [budgets]);
const iconGlyph = BUDGET_ICON.get(budgets.type);
const alertKind = BUDGET_ALERT_KIND.get(budgets.type);
const rootClassName = cx(css.group, className, css[`group-${alertKind}`]);

return (
<Stack className={className} space="xsmall">
{failedBudgets.length > 0 && (
<BudgetsGroup
kind="danger"
source={source}
budgets={failedBudgets}
CustomLink={CustomLink}
/>
)}
<Alert kind={alertKind} padding="none" className={rootClassName}>
<Box
padding={['xsmall', 'small']}
className={css.groupHeader}
as="button"
type="button"
onClick={() => setShowBudgets(!showBudgets)}
>
<FlexStack space="xxsmall" className={css.groupTitle}>
{iconGlyph && <Icon className={css.groupIcon} glyph={iconGlyph} />}
<span>{budgets.message.text}</span>
<span className={css.groupTitleToggle}>{showBudgets ? 'hide' : 'show'} all</span>
</FlexStack>
</Box>

{passedBudgets.length > 0 && (
<BudgetsGroup
kind="success"
source={source}
budgets={passedBudgets}
CustomLink={CustomLink}
/>
{showBudgets && (
<Box padding={['xsmall', 'small']} className={css.groupContent}>
<Stack space="none">
{Object.entries(budgets.data).map(([key, budget]) => (
<Budget
key={key}
metricId={`${source}.${key}`}
budget={budget}
CustomLink={CustomLink}
/>
))}
</Stack>
</Box>
)}
</Stack>
</Alert>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@
margin: 0 0 0 auto !important;
}

.danger .groupIcon {
.group-danger .groupIcon {
color: var(--color-danger);
}

.success .groupIcon {
.group-warning .groupIcon {
color: var(--color-warning);
}

.group-success .groupIcon {
color: var(--color-success);
}

Expand Down

0 comments on commit 7a66a1e

Please sign in to comment.