mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-27 01:19:00 +02:00
fix: use technicalDebt property from backend (#10111)
Frontend should load `technicaDebt` from backend instead of re-calculating it.
This commit is contained in:
parent
d7da5fe6a4
commit
4e48d90ed8
@ -115,9 +115,7 @@ export const HealthTooltip: FC<{ tooltip: TooltipState | null }> = ({
|
||||
label: point.label,
|
||||
title: point.dataset.label,
|
||||
color: point.dataset.borderColor,
|
||||
value: point.raw as InstanceInsightsSchemaProjectFlagTrendsItem & {
|
||||
technicalDebt?: number | null;
|
||||
}, // TODO: get from backend
|
||||
value: point.raw as InstanceInsightsSchemaProjectFlagTrendsItem,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -5,6 +5,7 @@ import { useFlag } from '@unleash/proxy-client-react';
|
||||
|
||||
interface IHealthStatsProps {
|
||||
value?: string | number;
|
||||
technicalDebt?: string | number;
|
||||
healthy: number;
|
||||
stale: number;
|
||||
potentiallyStale: number;
|
||||
@ -66,6 +67,7 @@ const StyledMainValue = styled(StyledValue)(({ theme }) => ({
|
||||
|
||||
export const HealthStats: FC<IHealthStatsProps> = ({
|
||||
value,
|
||||
technicalDebt,
|
||||
healthy,
|
||||
stale,
|
||||
potentiallyStale,
|
||||
@ -73,13 +75,6 @@ export const HealthStats: FC<IHealthStatsProps> = ({
|
||||
}) => {
|
||||
const healthToDebtEnabled = useFlag('healthToTechDebt');
|
||||
|
||||
// TODO: get the following from backend
|
||||
const unhealthy = stale + potentiallyStale;
|
||||
const technicalDebtValue = (
|
||||
(unhealthy / (healthy + unhealthy)) *
|
||||
100
|
||||
).toFixed(1);
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledHeader>
|
||||
@ -91,7 +86,7 @@ export const HealthStats: FC<IHealthStatsProps> = ({
|
||||
<StyledIcon />
|
||||
{healthToDebtEnabled ? 'Technical debt' : 'Instance health'}
|
||||
{healthToDebtEnabled ? (
|
||||
<StyledMainValue>{`${technicalDebtValue}%`}</StyledMainValue>
|
||||
<StyledMainValue>{`${technicalDebt}%`}</StyledMainValue>
|
||||
) : (
|
||||
<StyledMainValue>{`${value || 0}%`}</StyledMainValue>
|
||||
)}
|
||||
|
@ -64,6 +64,7 @@ describe('useFilteredFlagTrends', () => {
|
||||
averageUsers: 2,
|
||||
averageHealth: '79',
|
||||
medianTimeToProduction: 3,
|
||||
technicalDebt: '21',
|
||||
});
|
||||
});
|
||||
|
||||
@ -92,6 +93,7 @@ describe('useFilteredFlagTrends', () => {
|
||||
potentiallyStale: 0,
|
||||
averageUsers: 0,
|
||||
averageHealth: '100',
|
||||
technicalDebt: '0',
|
||||
medianTimeToProduction: 4,
|
||||
});
|
||||
});
|
||||
@ -134,6 +136,7 @@ describe('useFilteredFlagTrends', () => {
|
||||
averageUsers: 1.5,
|
||||
averageHealth: '100',
|
||||
medianTimeToProduction: 3.5,
|
||||
technicalDebt: '0',
|
||||
});
|
||||
});
|
||||
|
||||
@ -163,6 +166,7 @@ describe('useFilteredFlagTrends', () => {
|
||||
averageUsers: 0,
|
||||
averageHealth: '100',
|
||||
medianTimeToProduction: undefined,
|
||||
technicalDebt: '0',
|
||||
});
|
||||
});
|
||||
|
||||
@ -216,6 +220,7 @@ describe('useFilteredFlagTrends', () => {
|
||||
averageUsers: 0,
|
||||
averageHealth: '100',
|
||||
medianTimeToProduction: 5,
|
||||
technicalDebt: '0',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -71,6 +71,12 @@ export const useFilteredFlagsSummary = (
|
||||
averageHealth: sum.total
|
||||
? ((sum.active / (sum.total || 1)) * 100).toFixed(0)
|
||||
: '100',
|
||||
technicalDebt: sum.total
|
||||
? (
|
||||
((sum.stale + sum.potentiallyStale) / sum.total) *
|
||||
100
|
||||
).toFixed(0)
|
||||
: '0',
|
||||
medianTimeToProduction,
|
||||
};
|
||||
}, [filteredProjectFlagTrends]);
|
||||
|
@ -130,6 +130,7 @@ export const PerformanceInsights: FC = () => {
|
||||
<StyledWidgetStats width={350} padding={0}>
|
||||
<HealthStats
|
||||
value={summary.averageHealth}
|
||||
technicalDebt={summary.technicalDebt}
|
||||
healthy={summary.active}
|
||||
stale={summary.stale}
|
||||
potentiallyStale={summary.potentiallyStale}
|
||||
|
@ -46,7 +46,7 @@ const ActiveProjectDetails: FC<{
|
||||
}> = ({ project }) => {
|
||||
const healthToTechDebtEnabled = useFlag('healthToTechDebt');
|
||||
|
||||
const techicalDebt = 100 - project.health; // TODO: health to technical debt from backend
|
||||
const techicalDebt = project.technicalDebt;
|
||||
return (
|
||||
<Box sx={{ display: 'flex', gap: 2 }}>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
|
||||
|
@ -115,23 +115,25 @@ const Wrapper = styled(HealthGridTile)(({ theme }) => ({
|
||||
export const ProjectHealth = () => {
|
||||
const projectId = useRequiredPathParam('projectId');
|
||||
const {
|
||||
data: { health, staleFlags },
|
||||
data: { health, technicalDebt, staleFlags },
|
||||
} = useProjectStatus(projectId);
|
||||
const { isOss } = useUiConfig();
|
||||
const theme = useTheme();
|
||||
const healthToDebtEnabled = useFlag('healthToTechDebt');
|
||||
const circumference = 2 * Math.PI * ChartRadius;
|
||||
const healthRating = health.current;
|
||||
const technicalDebt = 100 - healthRating; // TODO: get from backend
|
||||
|
||||
const gapLength = 0.3;
|
||||
const filledLength = 1 - gapLength;
|
||||
const offset = 0.75 - gapLength / 2;
|
||||
const healthLength = (healthRating / 100) * circumference * 0.7;
|
||||
const technicalDebtLength = (technicalDebt / 100) * circumference * 0.7;
|
||||
const technicalDebtLength =
|
||||
((technicalDebt.current || 0) / 100) * circumference * 0.7;
|
||||
|
||||
const healthColor = useHealthColor(healthRating);
|
||||
const technicalDebtColor = useTechnicalDebtColor(technicalDebt);
|
||||
const technicalDebtColor = useTechnicalDebtColor(
|
||||
technicalDebt.current || 0,
|
||||
);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
@ -174,7 +176,9 @@ export const ProjectHealth = () => {
|
||||
fill={theme.palette.text.primary}
|
||||
fontSize={theme.typography.h1.fontSize}
|
||||
>
|
||||
{healthToDebtEnabled ? technicalDebt : healthRating}
|
||||
{healthToDebtEnabled
|
||||
? technicalDebt.current || 0
|
||||
: healthRating}
|
||||
%
|
||||
</text>
|
||||
</StyledSVG>
|
||||
|
@ -20,6 +20,18 @@ const mockMetrics = {
|
||||
};
|
||||
|
||||
describe('productivityReportViewModel', () => {
|
||||
it('should show technical debt', () => {
|
||||
const viewModel = productivityReportViewModel({
|
||||
...mockData,
|
||||
metrics: {
|
||||
...mockMetrics,
|
||||
health: 85,
|
||||
},
|
||||
});
|
||||
|
||||
expect(viewModel.technicalDebt).toBe('15');
|
||||
});
|
||||
|
||||
describe('healthColor', () => {
|
||||
it('returns RED for health between 0 and 24', () => {
|
||||
const metrics: ProductivityReportMetrics = {
|
||||
@ -65,7 +77,7 @@ describe('productivityReportViewModel', () => {
|
||||
});
|
||||
|
||||
describe('healthTrendMessage', () => {
|
||||
it('returns correct trend message when health increased', () => {
|
||||
it('returns correct trend message when technica debt decreased', () => {
|
||||
const metrics: ProductivityReportMetrics = {
|
||||
...mockMetrics,
|
||||
health: 80,
|
||||
@ -82,7 +94,7 @@ describe('productivityReportViewModel', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('returns correct trend message when health decreased', () => {
|
||||
it('returns correct trend message when technical debt increased', () => {
|
||||
const metrics: ProductivityReportMetrics = {
|
||||
...mockMetrics,
|
||||
health: 60,
|
||||
@ -99,7 +111,7 @@ describe('productivityReportViewModel', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('returns correct message when health is the same', () => {
|
||||
it('returns correct message when technical debt is the same', () => {
|
||||
const metrics: ProductivityReportMetrics = {
|
||||
...mockMetrics,
|
||||
health: 70,
|
||||
|
@ -27,6 +27,7 @@ export const productivityReportViewModel = ({
|
||||
userName,
|
||||
userEmail,
|
||||
...metrics,
|
||||
technicalDebt: Math.max(0, 100 - metrics.health).toString(),
|
||||
unleashUrl,
|
||||
healthColor() {
|
||||
const healthRating = this.health;
|
||||
|
@ -141,14 +141,53 @@ test('Can send productivity report email', async () => {
|
||||
);
|
||||
expect(content.from).toBe('noreply@getunleash.ai');
|
||||
expect(content.subject).toBe('Unleash - productivity report');
|
||||
expect(content.html.includes('Productivity Report')).toBe(true);
|
||||
expect(content.html.includes('localhost/insights')).toBe(true);
|
||||
expect(content.html.includes('localhost/profile')).toBe(true);
|
||||
expect(content.html.includes('#68a611')).toBe(true);
|
||||
expect(content.html.includes('10% more than previous month')).toBe(true);
|
||||
expect(content.text.includes('localhost/insights')).toBe(true);
|
||||
expect(content.text.includes('localhost/profile')).toBe(true);
|
||||
expect(content.text.includes('localhost/profile')).toBe(true);
|
||||
expect(content.html).toContain('Productivity Report');
|
||||
expect(content.html).toContain('localhost/insights');
|
||||
expect(content.html).toContain('localhost/profile');
|
||||
expect(content.html).toContain('#68a611');
|
||||
expect(content.html).toContain('1%');
|
||||
expect(content.html).toContain('10% more than previous month');
|
||||
expect(content.text).toContain('localhost/insights');
|
||||
expect(content.text).toContain('localhost/profile');
|
||||
expect(content.text).toContain('localhost/profile');
|
||||
expect(content.text).toContain('Your instance technical debt: 1%');
|
||||
});
|
||||
|
||||
test('Sets correct color for technical debt', async () => {
|
||||
const emailService = new EmailService({
|
||||
server: {
|
||||
unleashUrl: 'http://localhost',
|
||||
},
|
||||
email: {
|
||||
host: 'test',
|
||||
port: 587,
|
||||
secure: false,
|
||||
smtpuser: '',
|
||||
smtppass: '',
|
||||
sender: 'noreply@getunleash.ai',
|
||||
},
|
||||
getLogger: noLoggerProvider,
|
||||
} as unknown as IUnleashConfig);
|
||||
|
||||
const content = await emailService.sendProductivityReportEmail(
|
||||
'user@user.com',
|
||||
'customerId',
|
||||
{
|
||||
flagsCreated: 1,
|
||||
productionUpdates: 2,
|
||||
health: 20,
|
||||
previousMonth: {
|
||||
health: 50,
|
||||
flagsCreated: 1,
|
||||
productionUpdates: 3,
|
||||
},
|
||||
},
|
||||
);
|
||||
expect(content.html).not.toContain('#68a611');
|
||||
expect(content.html).toContain('#d93644');
|
||||
expect(content.html).toContain(
|
||||
'Remember to archive stale flags to reduce technical debt and keep your project healthy',
|
||||
);
|
||||
});
|
||||
|
||||
test('Should add optional headers to productivity email', async () => {
|
||||
|
@ -27,8 +27,8 @@
|
||||
<div class="shaded"
|
||||
style="margin: 0;padding: 24px 8px 24px 8px; background: #f0f0f5;border-width: 3px;border-color: #ffffff;border-style: solid;">
|
||||
<div style="padding-top: 12px;">
|
||||
<span style="color: {{healthColor}};">{{health}}%</span><br>
|
||||
<span style="font-size: 16px; color: #1A4049; font-weight: 700">your instance health</span><br>
|
||||
<span style="color: {{healthColor}};">{{technicalDebt}}%</span><br>
|
||||
<span style="font-size: 16px; color: #1A4049; font-weight: 700">your instance technical debt</span><br>
|
||||
<span style="font-size: 12px; color: #6E6E70; font-weight: 400; line-height: 14px">{{{healthTrendMessage}}}</span>
|
||||
<div style="font-size: 12px; margin-top: 16px; font-weight: 400; line-height: 14px;">{{actionText}}</div>
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@ Hi {{userName}},
|
||||
We are excited to share the latest insights for your instance. As always if you
|
||||
have any questions or concerns let us know - we are here for you.
|
||||
|
||||
Your instance health: {{health}}
|
||||
Your instance technical debt: {{technicalDebt}}%
|
||||
|
||||
Flags created last month: {{flagsCreated}}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user