Skip to content

Commit

Permalink
WIP: BudgetInsights
Browse files Browse the repository at this point in the history
  • Loading branch information
vio committed Dec 14, 2021
1 parent eed8ab7 commit 9c8c86f
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 0 deletions.
98 changes: 98 additions & 0 deletions packages/ui/src/components/budget-insights/budget-insights.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { getGlobalMetricType } from '@bundle-stats/utils';

import { Stack } from '../../layout/stack';
import { Alert } from '../../ui/alert';
import css from './budget-insights.module.css';

const Budget = (props) => {
const { className, metricKey, overBudget, value, budget } = props;
const metric = getGlobalMetricType(metricKey);

return (
<p className={className}>
<strong>{metric.label}</strong>
{` is ${overBudget ? 'over' : 'under'} `}
<strong>{metric.formatter(budget)}</strong>
{` budget`}
</p>
);
};

export const BudgetInsights = (props) => {
const { className, source, budgets } = props;
const [showPassedBudgets, setShowPassedBudgets] = useState(false);

const [failedBudgets, passedBudgets] = useMemo(() => {
const passed = [];
const failed = [];

Object.entries(budgets).forEach(([key, budget]) => {
if (budget.overBudget) {
failed.push([key, budget]);
} else {
passed.push([key, budget]);
}
});

return [failed, passed];
}, [budgets]);

return (
<Stack className={className} space="xsmall">
<Alert kind="danger">
<Stack space="xxxsmall">
{failedBudgets.map(([key, budget]) => (
<Budget
key={key}
source={source}
metricKey={`${source}.${key}`}
{...budget}
/>
))}
</Stack>
</Alert>

{passedBudgets.length > 0 && (
<Stack space="xxxsmall">
<p>
<strong>{passedBudgets.length}</strong> budgets passed
<button
className={css.passedBudgetsButton}
type="button"
onClick={() => setShowPassedBudgets(!showPassedBudgets)}
>
{showPassedBudgets ? 'hide': 'show'}
</button>
</p>

{showPassedBudgets && (
<Alert kind="success">
<Stack space="xxxsmall">
{passedBudgets.map(([key, budget]) => (
<Budget
key={key}
source={source}
metricKey={`${source}.${key}`}
{...budget}
/>
))}
</Stack>
</Alert>
)}
</Stack>
)}
</Stack>
);
};

BudgetInsights.propTypes = {
className: PropTypes.string,
source: PropTypes.string.isRequired,
budgets: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};

BudgetInsights.defaultProps = {
className: '',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.passedBudgetsButton {
border: none;
background: none;
padding: none;
cursor: pointer;
}

.passedBudgetsButton:hover {
color: var(--color-primary);
text-decoration: underline;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';

import { BudgetInsights } from '.';

export default {
title: 'Components/BudgetInsights',
component: BudgetInsights,
};

const Template = (args) => <BudgetInsights {...args} />;

export const Default = Template.bind();

Default.args = {
source: 'webpack',
budgets: {
totalSizeByTypeALL: {
value: 2097917,
budget: 2097152,
overBudget: true,
},
totalInitialSizeJS: {
value: 1265645,
budget: 524288,
overBudget: true,
},
totalInitialSizeCSS: {
value: 48866,
budget: 51200,
overBudget: false,
},
chunkCount: {
value: 12,
budget: 50,
overBudget: false,
},
moduleCount: {
value: 1059,
budget: 2000,
overBudget: false,
},
duplicatePackagesCount: {
value: 13,
budget: 5,
overBudget: true,
},
'sizes.totalSizeByTypeJS': {
value: 1981470,
budget: 2097152,
overBudget: false,
},
'sizes.totalSizeByTypeCSS': {
value: 56091,
budget: 20480,
overBudget: true,
},
},
};
1 change: 1 addition & 0 deletions packages/ui/src/components/budget-insights/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './budget-insights';

0 comments on commit 9c8c86f

Please sign in to comment.