Merge pull request #432 from buster-so/big-nate/bus-1280-displaying-0-instead-of-a-null-string

fix replace missing data with logic
This commit is contained in:
Nate Kelley 2025-07-07 16:45:01 -06:00 committed by GitHub
commit 665ee9fd07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 100 additions and 5 deletions

View File

@ -0,0 +1,65 @@
import type { Meta, StoryObj } from '@storybook/react';
import { faker } from '@faker-js/faker';
import { DataContainer } from './DataContainer';
import type { DataResult } from '@buster/server-shared/metrics';
// Generate mock data that would be compatible with AppDataGrid
const generateMockData = (): DataResult => {
const columns = ['id', 'name', 'email', 'department', 'salary', 'join_date'];
const rows = Array.from({ length: 50 }, (_, index) => ({
id: faker.string.uuid(),
name: faker.person.fullName(),
email: index % 3 === 2 ? null : faker.internet.email(),
department: faker.commerce.department(),
salary: faker.number.int({ min: 40000, max: 150000 }),
join_date: faker.date.past({ years: 5 }).toISOString().split('T')[0]
}));
return rows as DataResult;
};
const meta = {
title: 'Features/Layouts/DataContainer',
component: DataContainer,
parameters: {
layout: 'fullscreen'
},
decorators: [
(Story) => (
<div style={{ height: '600px', padding: '20px' }}>
<Story />
</div>
)
]
} satisfies Meta<typeof DataContainer>;
export default meta;
type Story = StoryObj<typeof meta>;
export const WithData: Story = {
args: {
data: generateMockData(),
fetchingData: false
}
};
export const Loading: Story = {
args: {
data: null,
fetchingData: true
}
};
export const LoadingWithData: Story = {
args: {
data: generateMockData(),
fetchingData: true
}
};
export const NoData: Story = {
args: {
data: null,
fetchingData: false
}
};

View File

@ -1,6 +1,6 @@
import type { Meta, StoryObj } from '@storybook/react';
import { BusterTableChart } from '../TableChart/BusterTableChart';
import type { ColumnLabelFormat } from '@buster/server-shared/metrics';
import { DEFAULT_COLUMN_LABEL_FORMAT, type ColumnLabelFormat } from '@buster/server-shared/metrics';
// Helper functions for generating sample data
const generateProductName = (index: number) => `Product ${index + 1}`;
@ -281,3 +281,19 @@ export const CustomClassname: Story = {
);
}
};
export const WithNullStringValues: Story = {
args: {
data: generateTableData().map((item, index) => ({
...item,
product: index % 2 === 0 ? null : item.product
})),
columnLabelFormats: {
product: {
...DEFAULT_COLUMN_LABEL_FORMAT,
columnType: 'text',
style: 'string'
} as ColumnLabelFormat
}
}
};

View File

@ -243,7 +243,7 @@ describe('formatLabel', () => {
style: 'string',
replaceMissingDataWith: 0
})
).toBe('0');
).toBe('null');
});
it('should handle replaceMissingDataWith for undefined values with string', () => {
@ -351,5 +351,11 @@ describe('formatLabel', () => {
formatLabel(null, { columnType: 'date', style: 'date', replaceMissingDataWith: 'N/A' })
).toBe('N/A');
});
it('should not allow replaceMissingDataWith to be a number when columnType is text', () => {
expect(
formatLabel(null, { columnType: 'text', style: 'string', replaceMissingDataWith: 0 })
).toBe('null');
});
});
});

View File

@ -57,9 +57,17 @@ export const formatLabel = (
replaceMissingDataWith ?? DEFAULT_COLUMN_LABEL_FORMAT.replaceMissingDataWith
);
}
} else if (replaceMissingDataWith !== undefined) {
formattedText = String(replaceMissingDataWith);
} else formattedText = String('null');
}
// I removed this because it was causing issues with null values and strings...
else if (replaceMissingDataWith !== undefined) {
if (columnType === 'text' && typeof replaceMissingDataWith !== 'number') {
formattedText = String(replaceMissingDataWith);
} else if (columnType !== 'text') {
formattedText = String(replaceMissingDataWith);
}
} else {
formattedText = String('null');
}
} else if (style === 'date' && !useKeyFormatter) {
formattedText = formatLabelDate(text as string | number | Date, {
dateFormat,