Prevent events chart on pixel and link boards

This commit is contained in:
Mike Cao committed 2026-03-10 00:23:19 -07:00
1 parent 6629ab598b
commit 54023e3796
3 files changed
+65 -4

No files matched your search

@@ -20,6 +20,7 @@ import {
type BoardEntityType,
type BoardType,
getComponentEntity,
isBoardComponentSupported,
isOpenBoardType,
} from '@/lib/boards';
import {
@@ -64,6 +65,10 @@ export function BoardComponentSelect({
() => CATEGORIES.flatMap(category => getComponentsByCategory(category.key)),
[],
);
const activeEntityType = isOpenBoardType(boardType) ? selectedEntityType : boardEntityType;
const isSelectedDefSupported = selectedDef
? isBoardComponentSupported(selectedDef.type, activeEntityType)
: false;
const getDefaultConfigValues = (def: ComponentDefinition, config?: BoardComponentConfig) => {
const defaults: Record<string, any> = {};
@@ -90,7 +95,11 @@ export function BoardComponentSelect({
const definition = allDefinitions.find(def => def.type === initialConfig.type);
if (!definition) {
if (!definition || !isBoardComponentSupported(definition.type, activeEntityType)) {
setSelectedDef(null);
setConfigValues({});
setTitle('');
setDescription('');
return;
}
@@ -105,12 +114,24 @@ export function BoardComponentSelect({
}, [
initialConfig,
allDefinitions,
activeEntityType,
boardEntityId,
boardEntityType,
initialEntity.entityId,
initialEntity.entityType,
]);
useEffect(() => {
if (!selectedDef || isSelectedDefSupported) {
return;
}
setSelectedDef(null);
setConfigValues({});
setTitle('');
setDescription('');
}, [isSelectedDefSupported, selectedDef]);
const handleSelectComponent = (def: ComponentDefinition) => {
setSelectedDef(def);
setConfigValues(getDefaultConfigValues(def));
@@ -141,7 +162,7 @@ export function BoardComponentSelect({
};
const handleAdd = () => {
if (!selectedDef || (needsWebsite && !resolvedEntityId)) return;
if (!selectedDef || !isSelectedDefSupported || (needsWebsite && !resolvedEntityId)) return;
const props: Record<string, any> = {};
@@ -182,14 +203,20 @@ export function BoardComponentSelect({
}
: null;
const canSave = !!selectedDef && (!needsWebsite || !!resolvedEntityId);
const canSave = !!selectedDef && isSelectedDefSupported && (!needsWebsite || !!resolvedEntityId);
return (
<Column gap="4">
<Row gap="4" style={{ height: 600 }}>
<Column gap="1" style={{ width: 280, flexShrink: 0, overflowY: 'auto' }}>
{CATEGORIES.map(category => {
const components = getComponentsByCategory(category.key);
const components = getComponentsByCategory(category.key).filter(def =>
isBoardComponentSupported(def.type, activeEntityType),
);
if (!components.length) {
return null;
}
return (
<Column key={category.key} gap="1" marginBottom="2">
+18
View File
@@ -0,0 +1,18 @@
import {
BOARD_ENTITY_TYPES,
isBoardComponentSupported,
} from '../boards';
test('isBoardComponentSupported allows events chart on website boards', () => {
expect(isBoardComponentSupported('EventsChart', BOARD_ENTITY_TYPES.website)).toBe(true);
});
test('isBoardComponentSupported rejects events chart on pixel and link boards', () => {
expect(isBoardComponentSupported('EventsChart', BOARD_ENTITY_TYPES.pixel)).toBe(false);
expect(isBoardComponentSupported('EventsChart', BOARD_ENTITY_TYPES.link)).toBe(false);
});
test('isBoardComponentSupported leaves other components available for all board entities', () => {
expect(isBoardComponentSupported('WebsiteChart', BOARD_ENTITY_TYPES.pixel)).toBe(true);
expect(isBoardComponentSupported('TextBlock', BOARD_ENTITY_TYPES.link)).toBe(true);
});
+16
View File
@@ -18,6 +18,9 @@ export type BoardType = (typeof BOARD_TYPES)[keyof typeof BOARD_TYPES];
export type BoardEntityType = (typeof BOARD_ENTITY_TYPES)[keyof typeof BOARD_ENTITY_TYPES];
const boardTypes = new Set<string>(Object.values(BOARD_TYPES));
const boardComponentEntityTypes: Partial<Record<string, readonly BoardEntityType[]>> = {
EventsChart: [BOARD_ENTITY_TYPES.website],
};
export function getLegacyBoardType(parameters?: BoardParameters): BoardType {
if (parameters?.pixelId) {
@@ -140,6 +143,19 @@ export function getResolvedComponentEntity(
return getComponentEntity(config);
}
export function isBoardComponentSupported(
componentType: string,
entityType?: BoardEntityType,
) {
const supportedEntityTypes = boardComponentEntityTypes[componentType];
if (!entityType || !supportedEntityTypes) {
return true;
}
return supportedEntityTypes.includes(entityType);
}
export function getFirstBoardComponentEntity(
board?: Pick<Board, 'type' | 'parameters'> | Partial<Board>,
) {